[AWTF 2019] Triangular Lamps Hard

[AWTF 2019] Triangular Lamps Hard

首先考虑将所有亮着的灯转移到同一行。

不妨令这一行的纵坐标为 \(V = -\infty\),考虑将一盏灯往下转移时的情况。

不妨考虑从上往下,一行一行转移,每次将亮着的灯作为三角形的上端顶点操作。

下面我们描述操作的过程,\(0\) 为灭,\(1\) 为亮:

  • \(0\) 次转移:\([1]\)

  • \(1\) 次转移:\([1,1]\)

  • \(2\) 次转移:\([1,0,1]\)

  • \(3\) 次转移:\([1,1,1,1]\)

  • \(4\) 次转移:\([1,0,0,0,1]\)

  • \(5\) 次转移:\([1,1,0,0,1,1]\)

我们发现,从 \((x,y)\) 出发,\((x-a,y+b)\) 的系数是 \(\dbinom{a}{b} \bmod 2\)。

显然,后者等价于 \(b \subseteq a\),而所有点对应的 \(a\) 在数据下都是可以计算的。

也就是说,我们可以 \(O(n)\) check 一个灯是否被点亮。

我们找到第 \(V\) 行最左边点亮的灯和最右边点亮的灯,通过这两个灯的位置即可求出答案。

具体地,假设坐标为 \((L,V)\) 和 \((R,V)\),答案为 \((L,V+R-L)\)。

接下来我们的任务是算出 \(L\) 和 \(R\),不妨继续观察性质。

将 \((x,y)\) 按照 \((x-y) \bmod 3\) 意义分类,则一次操作改动的三个点各不相同。

考虑 \((x-y) \equiv 0,1,2 \pmod 3\) 的 \((x,y)\) 个数奇偶性。

根据操作流程,这些点中必然存在一类的个数为奇数。

考虑找到一个奇数个数的类,接下来我们尝试找到该类中的任意一个亮着的点。

对这个问题尝试二分,显然 \(2k\) 只能分成 \(2p\) 和 \(2q+1\),每次取奇数的一边即可。

现在考虑如何求一段区间内模 \(3\) 为 \(r\) 且亮着的点的奇偶性。

这种模 \(2\) 意义下的问题,我们拆到原先的每个点上进行数位 dp,复杂度 \(O(n \log V)\)。

加上二分,这一步的时间复杂度是 \(O(n \log^2 V)\)。

接下来考虑找到一个点后该如何处理,考虑据此找到 L 和 R。

根据题目的性质,我们可以倍增,从大到小考虑 \(2^i\),判断横坐标是否能加减 \(2^i\)。

显然在组合数性质下,这个方法是正确的,这一步的时间复杂度 \(O(n \log V)\)。

时间复杂度 \(O(n \log^2 V)\)。

//Ad astra per aspera
#include<iostream>
#include<cstdio>
using namespace std;
const int C=60;
const long long V=-100000000000000000;
const long long L=-100000000000000000;
const long long R=300000000000000000;
int n;
long long x[10010],y[10010];
struct Data{
	bool ans[3];
}O,dta[C+10];
Data operator ^(const Data &lhs,const Data &rhs){
	Data hs;
	hs.ans[0]=lhs.ans[0]^rhs.ans[0];
	hs.ans[1]=lhs.ans[1]^rhs.ans[1];
	hs.ans[2]=lhs.ans[2]^rhs.ans[2];
	return hs;
}
Data qry(long long num,long long pos){
	Data ans=O,pre=O;
	pre.ans[0]=true;
	for(int i=0;i<=C;i++){
		dta[i]=pre;
		if(num&(1ll<<i)){
			Data tmp;
			if(i%2==0){
				tmp.ans[0]=pre.ans[2];
				tmp.ans[1]=pre.ans[0];
				tmp.ans[2]=pre.ans[1];
			}
			if(i%2==1){
				tmp.ans[0]=pre.ans[1];
				tmp.ans[1]=pre.ans[2];
				tmp.ans[2]=pre.ans[0];
			}
			pre=pre^tmp;
		}
	}
	long long sum=0;
	int pret=0;
	for(int i=C;i>=0;i--){
		if(pos&(1ll<<i)){
			if((sum&num)==sum){
				Data tmp;
				if(pret==0){
					tmp.ans[0]=dta[i].ans[0];
					tmp.ans[1]=dta[i].ans[1];
					tmp.ans[2]=dta[i].ans[2];
				}
				if(pret==1){
					tmp.ans[0]=dta[i].ans[2];
					tmp.ans[1]=dta[i].ans[0];
					tmp.ans[2]=dta[i].ans[1];
				} 
				if(pret==2){
					tmp.ans[0]=dta[i].ans[1];
					tmp.ans[1]=dta[i].ans[2];
					tmp.ans[2]=dta[i].ans[0];
				}
				ans=ans^tmp;
			}
			sum+=1ll<<i;
			if(i%2==0){
				pret=(pret+1)%3;
			}
			else{
				pret=(pret+2)%3;
			}
		}
	}
	return ans;
}
int mod_3(long long num){
	return (num%3+3)%3;
}
Data query(long long l,long long r){
	Data ans=O;
	for(int i=1;i<=n;i++){
		long long pre_l=x[i],pre_r=x[i]+(y[i]-V);
		long long now_l=max(l,pre_l),now_r=min(r,pre_r);
		if(now_l<=now_r){
			Data tmp=O,tmp2;
			tmp=tmp^qry(y[i]-V,now_l-pre_l);
			tmp=tmp^qry(y[i]-V,(now_r+1)-pre_l);
			if(mod_3(pre_l)==0){
				tmp2.ans[0]=tmp.ans[0];
				tmp2.ans[1]=tmp.ans[1];
				tmp2.ans[2]=tmp.ans[2];
			}
			if(mod_3(pre_l)==1){
				tmp2.ans[0]=tmp.ans[2];
				tmp2.ans[1]=tmp.ans[0];
				tmp2.ans[2]=tmp.ans[1];
			}
			if(mod_3(pre_l)==2){
				tmp2.ans[0]=tmp.ans[1];
				tmp2.ans[1]=tmp.ans[2];
				tmp2.ans[2]=tmp.ans[0];
			}
			ans=ans^tmp2;
		}
	}
	return ans;
}
long long div_2(long long num){
	if(num%2==0  ||  num>=0){
		return num/2;
	}
	else{
		return num/2-1;
	}
}
bool check(Data hs){
	return hs.ans[0]  ||  hs.ans[1]  ||  hs.ans[2];
}
int main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld %lld",&x[i],&y[i]);
	}
	long long l=L,r=R;
	Data tmp=query(l,r);
	int pre;
	if(tmp.ans[0]){
		pre=0;
	}
	if(tmp.ans[1]){
		pre=1;
	}
	if(tmp.ans[2]){
		pre=2;
	}
	while(l<r){
		long long mid=div_2(l+r);
		if(query(l,mid).ans[pre]){
			r=mid;
		}
		else{
			l=mid+1;
		}
	}
	for(int i=C;i>=0;i--){
		if(check(query(l-(1ll<<i),l-(1ll<<i)))){
			l-=(1ll<<i);
		}
		if(check(query(r+(1ll<<i),r+(1ll<<i)))){
			r+=(1ll<<i);
		}
	}
	printf("%lld %lld",l,V+r-l);
	return 0;
}
posted @ 2026-04-03 00:25  Oken喵~  阅读(29)  评论(0)    收藏  举报