Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2) (题解)

补题补题补题。。。。
这是一篇补题题解,赛中太菜。。。

这里是传送门

A.XORinacci
题意: 给你一个斐波那契异或数列,即f(0)=a,f(1)=b,f(2)=a^b …
然后让你求第n 项
根据异或的性质可以知道,b^ a^b =a , a^ a^b=b
所以可以知道,f[n]=f[n%3]

B.Uniquene
题意: 给你n个数,问你去掉一个最短的区间使得剩余的数没有重复元素
求最短区间长度

先从前找不重复最长的区间,再根据这个区间 从后找最长的区间,然后用区间长度减去即可

#include 
using namespace std;
const int MAX=2e3+5;
int a[MAX],ans;
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	set<int>s;ans=n-1;
	for(int i=0;i<n;i++){
		int flag=0;
		for(int j=0;j<i;j++){
			if(s.count(a[j])==1){ //出现重复元素就不算
				flag=1;
				break;
			}
			else s.insert(a[j]);
		}
		int minn=n;
		for(int j=n-1;j>=i;j--){
			if(s.count(a[j])==1){
				break;
			}
			else {
				s.insert(a[j]); //记录最长可行的下标
				minn=j;
			}
		}
		if(flag==0)
		ans=min(ans,minn-i);
		s.clear();
	}
	cout<<ans<<endl;
	return 0;
}

C.Magic Grid
题意: 给你一个4的倍数的数n,要你将0~(n^2- 1) 这n^2 个数填入n X n 的矩阵,使得矩阵的每一行、每一列异或的值就相同

这是一个思维题。 把要填的矩阵平均分成四个部分,左上,左下,右上,右下,然后在这四个部分中随意填0~n^2/4-1 中的数即可,并保证排列方式相同,这里我们可以就直接顺序排列。这样根据异或的性质,两个部分相同,所以异或都是0.比如

|0|1|0|1|
|2|3|2|3|
|0|1|0|1|
|2|3|2|3|

然后,我们将四个部分,分别乘以1 2 3 4这样,异或值仍然不变,而且每个数并不重复。

D.Restore Permutation
题意: 给你一个排列中,某数x前面所有小于x的数之和 的序列,让你求出原序列,保证这样子求出的序列是唯一的。

思路: 找到最后一个0的位置,位置一定是1 ,然后将这个数加上无穷大,将这个数后面所有的数都减去这个数,然后再重复上述过程。查询修改操作可以用线段树维护。

注意的地方有,初始输入的数组要开ll ,题目里面n为2e5 ,但是x就是n*(n-1)/2
//省赛要来了,之前不知道被ll 坑了多少次,我决定全员ll (大部分题不会卡内存吧。。。

#pragma GCC optimize(2)
#include 
using namespace std;
const int MAX=2e5+5;
typedef long long ll;
const ll INF = 1e13;
struct node {
	ll v,l,r;
	ll lazytag;
}tree[MAX*5];
inline void push_up(int k){
	tree[k].v=min(tree[k<<1].v,tree[k<<1|1].v);
}
ll ans[MAX],a[MAX];
inline void push_down(int k){
	if(tree[k].lazytag){
		tree[k<<1].lazytag+=tree[k].lazytag;
		tree[k<<1|1].lazytag+=tree[k].lazytag;
		tree[k<<1].v+=tree[k].lazytag;
		tree[k<<1|1].v+=tree[k].lazytag;
		tree[k].lazytag=0;
	}
}
inline void build(int l,int r,int root){
	if(l==r){
		tree[root].v=a[l];
		return ;
	}
	int mid=(l+r)/2;
	build(l,mid,root<<1);
    build(mid+1,r,root<<1|1);
	push_up(root);
}
inline void updata(int fl,int fr,ll v,int l,int r,int root){
	if(fl<=l&&fr>=r){
		tree[root].lazytag+=v;
		tree[root].v+=v;
		return ;
	}
	push_down(root);
	int mid=(l+r)/2;
	if(fl<=mid) updata(fl,fr,v,l,mid,root<<1);
	if(fr>mid)  updata(fl,fr,v,mid+1,r,root<<1|1);
	push_up(root);
}
inline int query(int l,int r,int root){
	ll ans=0;
	if(l==r){
		return l;
	}
	push_down(root);
	int mid=(l+r)/2;
	if(tree[root<<1|1].v==0) ans=query(mid+1,r,root<<1|1);
	else  ans=query(l,mid,root<<1);
	return ans;
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	} 
	build(1,n,1);
	for(int i=1;i<=n;i++){
		int x=query(1,n,1);
		updata(x,x,INF,1,n,1);
		if(x!=n)    //最后一个后面没有了!!! 
		updata(x+1,n,-i,1,n,1);
		ans[x]=i;
	//	cout<
	}
	
	for(int i=1;i<=n;i++){
		cout<<ans[i]<<" ";
	}
	cout<<endl;
	
	
	return 0;
} 

你可能感兴趣的:(cf题解)