CR668 题解

比赛入口

C. Fixed Point Removal

我们预处理一个数组,\(p_i\) 表示若想要删除 \(i\) 的最晚起点。

显然若 \(a_i=i\)\(p_i=i\),若 \(a_i<i\)\(p_i\) 为前面的第 \(i-a_i\) 大,这可以树状数组上二分做。

离线询问,每个询问即区间 \([l,r]\) 之间 \(p_i>=l\) 的个数,树状数组可做。

代码懒得写了,蒯了 \(verdandi\) 的用着:

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int n,m;
int a[maxn],ans[maxn],tr[maxn];
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define pb push_back
vector<pii>v[maxn];
void update(int x,int v){
	for(int i=x;i<=n;i+=i&(-i))tr[i]+=v;
}
int query(int x){
	int res=0;
	for(int i=x;i;i-=i&(-i))res+=tr[i];
	return res;
}
int getkth(int k){
	int res=0;
	for(int i=18;i>=0;i--)
		if(res+(1<<i)<=n&&k>tr[res+(1<<i)])
			k-=tr[res+(1<<i)],res+=(1<<i);
	return res+1;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	for(int i=1,x,y;i<=m;i++){
		x=read()+1,y=n-read();
		if(x<=y)v[y].pb(mkp(x,i));
	}
	for(int i=1;i<=n;i++){
		if(i-a[i]>=0){
			int pos=getkth(a[i]);
			update(min(i+1,pos),1);
		}else update(1,1);
		for(int j=0;j<v[i].size();j++)
			ans[v[i][j].se]=i-query(v[i][j].fi);
	}
	for(int i=1;i<=m;i++)
		printf("%d\n",ans[i]);
	return 0;
}

D. Game of Pairs

题意:交互,给定 \(n\) ,选择先后手,先手需要构造将 \(1\)\(2n\) 分为 \(n\) 对,使得不存在一种方案从每对中选一个和为 \(2n\) 的倍数;后手需要在交互库给定的 \(n\) 对中每对选出一个数使得和为 \(2n\) 的倍数。

考虑何时先手必胜。若 \(n=1\) 时显然先手负,\(n=2\) 时先手胜,不妨猜测 \(n\) 为偶数时先手必胜。事实的确如此,我们把 \(i\)\(i+n\) 放在一对,那么选出来的数必定是 \(\frac 12 n(n+1)+kn\) 不是 \(2n\) 的倍数。再考虑为什么 \(n\) 为奇数时必负。我们还是希望取出来的数能够是模 \(n\) 意义下的完全剩余系,这样如果我们取出的方案不行,则留下的一定行。考虑每对间连边,\(i\)\(i+n\) 之间连边,每个点的度数均为 \(2\) ,故会形成若干简单偶环,此时将图二分图染色,不难发现 \(i\)\(i+n\) 总不同色,故方案合法。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=1e6+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
int n,m,p[maxn],G[maxn],las[maxn],col[maxn],t[maxn],S;
inline void dfs(int x,int cur){
	if(col[x])return;col[x]=cur;
	dfs(G[x],3-cur);dfs((x+n-1)%(n+n)+1,3-cur);
}
int main(){
	n=read();
	if(n%2==0){
		cout<<"First"<<endl;
		for(int i=1;i<=n;i++)cout<<i<<" ";
		for(int i=1;i<=n;i++)cout<<i<<" ";
		cout<<endl;
	}else{
		cout<<"Second"<<endl;
		for(int i=1;i<=n+n;i++){
			p[i]=read();
			if(las[p[i]])
				G[las[p[i]]]=i,G[i]=las[p[i]];
			else las[p[i]]=i;
		}
		for(int i=1;i<=n+n;i++)
			if(!col[i])dfs(i,1);
		for(int i=1;i<=n+n;i++)
			if(col[i]==1)S=(S+i)%(n+n);
		int flg=(S?2:1);
		for(int i=1;i<=n+n;i++)
			if(col[i]==flg)printf("%d ",i);
		cout<<endl;
	}
    return 0;
}//
posted @ 2022-01-05 11:06  syzf2222  阅读(50)  评论(0编辑  收藏  举报