NEKAMELEONI

link

我是这个世界上最大的傻逼。考场上用1而不是1ll,于是一百变五十。

单点修改整体查询,考虑用线段树来维护。使用最大子段和的方法来维护每个区间前缀每次出现新数的位置和后缀每次出现新数的位置,这样一来在合并区间答案的时候可以直接用尺取法。这样一来就简单了,我用的 vector 来省空间,这也导致我的程序跑得很慢。

还是一道挺好的题。

因vector而极度繁杂的代码:

#include<bits/stdc++.h>
//#define feyn
#define int long long
const int N=100010;
const int M=50;
const int maxn=1e15;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline int min(int s1,int s2){
	return s1<s2?s1:s2;
}

int m,n,a[N],num;

#define lc (wh<<1)
#define rc (wh<<1|1)
#define mid (t[wh].l+t[wh].r>>1)
struct data{
	int pl,data;
};
struct node{
	int l,r,len;
	int all;vector<data>pre,suf;
}t[N<<2];
inline void pushup(int wh){
	t[wh].all=t[lc].all|t[rc].all;
	//work pre
	t[wh].pre.clear();int size=-1;
	for(int i=0;i<t[lc].pre.size();i++)size++,t[wh].pre.push_back(t[lc].pre[i]);
	for(int i=0;i<t[rc].pre.size();i++){
		int now=t[wh].pre[size].data|t[rc].pre[i].data;
		if(now>t[wh].pre[size].data){
			size++;
			t[wh].pre.push_back((data){t[rc].pre[i].pl,now});
		}
	}
	//work suf
	t[wh].suf.clear();size=-1;
	for(int i=0;i<t[rc].suf.size();i++)size++,t[wh].suf.push_back(t[rc].suf[i]);
	for(int i=0;i<t[lc].suf.size();i++){
		int now=t[wh].suf[size].data|t[lc].suf[i].data;
		if(now>t[wh].suf[size].data){
			size++;
			t[wh].suf.push_back((data){t[lc].suf[i].pl,now});
		}
	}
	//work len
	t[wh].len=min(t[lc].len,t[rc].len);
	if(t[wh].all!=(1ll<<n)-1)return;
	for(int i=0,j=t[rc].pre.size()-1;i<t[lc].suf.size();i++){
		//if(wh==1)printf("i=%lld j=%lld %lld\n",i,j,t[lc].suf[i].data|t[rc].pre[j].data);
		while(j>0&&(t[lc].suf[i].data|t[rc].pre[j-1].data)==(1ll<<n)-1)j--;
		if((t[lc].suf[i].data|t[rc].pre[j].data)!=(1ll<<n)-1)continue;
		t[wh].len=min(t[wh].len,t[rc].pre[j].pl-t[lc].suf[i].pl+1);
	}
}
inline void pushnow(int wh,int val){
	t[wh].all=(1ll<<val-1);
	t[wh].len=n==1?1:maxn;
	t[wh].pre.clear();
	t[wh].pre.push_back((data){t[wh].l,t[wh].all});
	t[wh].suf.clear();
	t[wh].suf.push_back((data){t[wh].l,t[wh].all});
}
inline void print(int wh){
	printf("now:%lld %lld data=%lld\n",t[wh].l,t[wh].r,t[wh].len);
	for(int i=0;i<t[wh].pre.size();i++)printf("%lld&%lld ",t[wh].pre[i].pl,t[wh].pre[i].data);
	printf("\n");
	for(int i=0;i<t[wh].suf.size();i++)printf("%lld&%lld ",t[wh].suf[i].pl,t[wh].suf[i].data);
	printf("\n");
}
inline void build(int wh,int l,int r){
	t[wh].l=l,t[wh].r=r;
	if(l==r){pushnow(wh,a[l]);return;}
	build(lc,l,mid);
	build(rc,mid+1,r);
	pushup(wh);
	/*
	printf("now:%lld %lld data=%lld\n",l,r,t[wh].len);
	for(int i=0;i<t[wh].pre.size();i++)printf("%lld&%lld ",t[wh].pre[i].pl,t[wh].pre[i].data);
	printf("\n");
	for(int i=0;i<t[wh].suf.size();i++)printf("%lld&%lld ",t[wh].suf[i].pl,t[wh].suf[i].data);
	printf("\n");
	*/
}
inline void change(int wh,int pl,int val){
	if(t[wh].l==t[wh].r){
		pushnow(wh,val);return;
	}
	change(pl<=mid?lc:rc,pl,val);
	pushup(wh);
	//print(wh);
}
#undef lc
#undef rc
#undef mid

signed main(){
	
	#ifdef feyn
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);read(num);
	for(int i=1;i<=m;i++)read(a[i]);
	build(1,1,m);
	
	
	int s1,s2,s3;
	while(num--){
		read(s1);
		if(s1==2)printf("%lld\n",t[1].len==maxn?-1:t[1].len);
		else{
			read(s2);read(s3);
			change(1,s2,s3);
		}
	}
	
	
	return 0;
}
posted @ 2022-07-20 20:04  Feyn618  阅读(18)  评论(0编辑  收藏  举报