补题补题补题。。。。
这是一篇补题题解,赛中太菜。。。
这里是传送门
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;
}