爆零代码求调 qwq
查看原帖
爆零代码求调 qwq
706523
AlicX楼主2023/6/1 19:10

自己调崩了,思路写在代码里。

#include<bits/stdc++.h>
#define il inline 
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+10,M=1e6+10;
int n,m;
int id=0;
int tr[N];
int ans[N];
int pre[N];
int a[N],t[N];
set<pii> col,s[N];
struct Query{
	int id;
	int l,r,x;
}q[N];
struct Node{
	int x,y,z;
	int k,d,ans;
	il bool operator<(const Node& Cyan)const{
		if(x!=Cyan.x) return x<Cyan.x;
		if(y!=Cyan.y) return y<Cyan.y;
		return z<Cyan.z; 
	}
}w[M],Pw[M>>1];//M>>1: 除了最大的区间外,最长区间只有 M/2  
/*
x 代表询问的位置
y 右端点 
z 代表同颜色的前一个位置
k 表示属性 
d 树状数组的加减(维护pre数组) 
ans 记录答案 
*/
il 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<<3)+(x<<1)+c-48;
		c=getchar();
	}
	return x*f;
}
il void write(int x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+48);
}
il int lowbit(int x){ return x&-x; }
il void add(int x,int val){ x++;
	for(int i=x;i<N;i+=lowbit(i)) tr[i]+=val; 
}
il int query(int x){
	int res=0; x++;
	for(int i=x;i;i-=lowbit(i)) res+=tr[i];
	return res;
}
il void split(int x){ 
	auto it=col.lower_bound({x+1,0});  
	int itr=it->first-1; --it; 
	int itl=it->first; if(x==itr) return ; 
	int color=it->second; col.erase(it); 
	col.insert({itl,color}),col.insert({x+1,color}); 
	s[color].insert({itl,x}),s[color].insert({x+1,itr}); 
}
il void assgin(int l,int r,int c,int p){
	split(l-1),split(r); 
	for(auto it=col.lower_bound({l,0});it->first<=r;){
		int x=it->first,color=it->second; it++; 
		int nxt=it->first-1; s[color].erase({x,nxt}); col.erase({x,color});
		if(x==l){ //特殊情况 
			int cor=(--(s[c].upper_bound({x,0})))->second;// 找到目标颜色的下标在当前位置的前一个位置 
			if(pre[x]!=cor){ 
				w[++id]={p,x,pre[x],0,-1,0};
				pre[x]=cor; w[++id]={p,x,pre[x],0,1,0};  
			} 
		} else{ // 普通情况 
			if(pre[x]!=x-1){
				//说明此颜色和x的颜色不同,由于我们是区间赋值,所以把他们变成一样的color 
				w[++id]={p,x,pre[x],0,-1,0};
				pre[x]=x-1; w[++id]={p,x,pre[x],0,1,0};  
			} 
		} x=nxt+1; nxt=(s[color].lower_bound({x,0}))->first; //下一个区间
		int lst=(--s[color].lower_bound({l,0}))->second;// l的前一个区间  
		if(nxt>r&&nxt<=n&&pre[nxt]!=lst){
			w[++id]={p,nxt,pre[nxt],0,-1,0};
			pre[nxt]=lst; w[++id]={p,nxt,pre[nxt],0,1,0};
		} //因为l这个区间没了,所以将他的后续区间连上前面的 
	} int x=(s[c].lower_bound({r+1,0}))->first; //赋值颜色的后继区间 
	if(x<=n&&pre[x]!=r){ 
		w[++id]={p,x,pre[x],0,-1,0};
		pre[x]=r; w[++id]={p,x,pre[x],0,1,0}; 
	} s[c].insert({l,r}); col.insert({l,c}); x=r+1; //添加上l,r这一段新区间 
	if(x<=n){
		int color=(col.lower_bound({x,0}))->second;// 找到在r以后的第一段区间的颜色 
		int lst=(--s[color].lower_bound({x,0}))->first; //找到这种颜色的上一个区间 
		if(pre[x]!=lst){ // 说明l-r中包含这种颜色,但l-r已被删除,所以重新赋值 
			w[++id]={p,x,pre[x],0,-1,0};
			pre[x]=lst; w[++id]={p,x,pre[x],0,1,0};
		}
	}
}
il void CDQ(int l,int r){
	//三维偏序:1.时间 2.右端点 3.pre 
	if(l==r) return ;
	int mid=l+r>>1,i=l,ID=0;
	CDQ(l,mid),CDQ(mid+1,r);
	for(int j=mid+1;j<=r;j++){	
		while(i<=mid&&w[i].y<=w[j].y){
			if(!w[i].k) add(w[i].z,w[i].d);
			if(l!=1||r!=id) Pw[++ID]=w[i]; i++;
		} if(w[j].k) w[j].ans+=query(w[j].z); if(l!=1||r!=id) Pw[++ID]=w[j];
	} while(i<=mid){ 
		if(!w[i].k) add(w[i].z,w[i].d);
		if(l!=1||r!=id) Pw[++ID]=w[i]; i++;
	} for(int k=l;k<=mid;k++) if(!w[k].k) add(w[k].z,-w[k].d);  
	if(l!=1||r!=id) for(int k=1;k<=ID;k++) w[l+k-1]=Pw[k]; //将这层的信息更新后返回上一层 
}
signed main(){
	int cnt; n=cnt=read(),m=read();
	for(int i=1;i<=n;i++) a[i]=read(),t[i]=a[i]; 
	for(int i=1;i<=m;i++){
		q[i].id=read(),q[i].l=read(),q[i].r=read();
		if(q[i].id==1) q[i].x=read(),t[++cnt]=q[i].x;
	} sort(t+1,t+cnt+1); cnt=unique(t+1,t+cnt+1)-t-1; 
	for(int i=1;i<=n;i++) a[i]=lower_bound(t+1,t+cnt+1,a[i])-t;
	for(int i=1;i<=m;i++) if(q[i].id==1) q[i].x=lower_bound(t+1,t+cnt+1,q[i].x)-t;
	for(int i=1;i<=cnt;i++) s[i].insert({0,0}); //边界 
	for(int i=1;i<=n;i++){
		pre[i]=(--s[a[i]].end())->second; //找到 a[i] 这种颜色最后出现的位置  
		w[++id]={0,i,pre[i],0,1,0};  
		s[a[i]].insert({i,i}),col.insert({i,a[i]}); 
	} for(int i=1;i<=cnt;i++) s[i].insert({n+1,0}); //边界 
	col.insert({0,0}),col.insert({n+1,n+1}); //边界 
	for(int i=1;i<=m;i++){
		if(q[i].id==1) assgin(q[i].l,q[i].r,q[i].x,i);
		else w[++id]={i,q[i].r,q[i].l-1,1,1,0},w[++id]={i,q[i].l-1,q[i].l-1,1,-1,0}; 
	} sort(w+1,w+id+1); CDQ(1,id); 
	for(int i=1;i<=id;i++) if(w[i].k) ans[w[i].x]+=w[i].ans*w[i].d;//在原来的位置上累加颜色 
	for(int i=1;i<=m;i++) if(q[i].id==2) write(ans[i]),puts("");
	return 0;
} 
2023/6/1 19:10
加载中...