CODECHEF DISTNUM: Simple Queries(三维偏序)

题面

首先这个离谱的询问一:在这里插入图片描述
关于不同的数的和,可以构造求出每个点 ( x , S x ) (x,S_x) 的前面第一个 ( y , S y = S x ) (y,S_y =S_x) ,那么把 ( y , x ) (y,x) 看做一个二维平面上的点,那么对 [ l , r ] [l,r] 中不同数的个数即为 y < l , l x r y \lt l , l \leq x \leq r 的点数。

那么在没有插入删除的情况下这就是一个三维偏序(注意128MB卡内存,可以用离线的方法树状数组套树状数组空间 O ( n log n ) O(n\log n) 求解。)

有插入删除的情况,先离线用平衡树模拟一遍转化为没有插入删除即可。

A C C o d e \mathcal AC Code

#include<bits/stdc++.h>
#define maxn 200005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define LL long long
#define Ct const
#define mod 1000000007
#define iv6 166666668ll
using namespace std;

char Start;

namespace IO{
	char cb[1<<16],*cs=cb,*ct=cb;
	#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
	void read(int &res){
		char ch;
		for(;!isdigit(ch=getc()););
		for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
	}
}
using IO::read;

int n,q;

namespace Solver1{
	int a[2 * maxn] , b[2 * maxn];
	void solve(){
		rep(i,1,n) read(a[i]);
		for(int op,x,y;q--;){
			read(op),read(x);
			if(op == 3){
				rep(i,x,n-1) a[i] = a[i+1];
				n--;
				continue;
			}
			read(y);
			if(op == 2)
				a[x] = y;
			if(op == 4){
				per(i,n+1,x+2) a[i] = a[i-1];
				a[x+1] = y;
			}
			if(op == 1 || op == 5){
				int cnt = 0;
				rep(i,x,y) b[++cnt] = a[i];
				sort(b+1,b+1+cnt);
				cnt = unique(b+1,b+1+cnt) - b - 1;
				LL ans = 0;
				if(op == 1){
					LL s0 = 1 , s1 = 0 , s2 = 0;
					rep(i,1,cnt)
						ans = (ans + s2 * b[i]) % mod ,
						s2 = (s2 + s1 * b[i]) % mod ,
						s1 = (s1 + s0 * b[i]) % mod ;
				}
				else{
					ans = cnt;
				}
				printf("%lld\n",ans);
			}
		}
	}
}

set<int>st[maxn];
int sb[maxn];
int dat[maxn][3],A[maxn],N,B[maxn];

void add(int &u,int v){ (u += v) >= mod && (u -= mod); }

#define pii pair<int,int>
#define mp make_pair
#define pb push_back
namespace BIT{
	#define maxp 100000 * 20
	int ans[maxn][4];
	vector<pair<int,int> >Q[maxn];
	int tr[4][maxn],vis[maxn],tim;
	void upd(int u,int v,int *tr){ 
		for(;u<=N;u+=u&-u){
			if(vis[u] != tim){
				vis[u] = tim;
				rep(i,0,3) 
					BIT::tr[i][u] = 0;
			}
			add(tr[u],v); 
		}
	}
	int qry(int u,int*tr){ int r=0;for(;u;u-=u&-u) if(vis[u] == tim) add(r,tr[u]);return r; }
	
	void Add(int a,int b,int v,int val){
		a++;
		int B = b;
		val *= v;
		for(;b <= N;b += b&-b)
			Q[b].pb(mp(a,val)) , Q[b].pb(mp(B+1,-val));
	}
	
	void del(int u){
		if(B[u] == -1) return;
		set<int>&s = st[lower_bound(sb+1,sb+1+sb[0],B[u])-sb];
		
		set<int>::iterator it = s.lower_bound(u) , it2 = it;
		if(it == s.begin()) 
			Add(0,u,-1,B[u]);
		else 
			it--,Add(*it,u,-1,B[u]),it++;
		if((++it2) != s.end()){
			Add(u,*it2,-1,B[u]);
			if(it == s.begin()) 
				Add(0,*it2,1,B[u]);
			else 
				it--,Add(*it,*it2,1,B[u]),it++;
		}
		s.erase(it);
		B[u] = -1;
	}
	
	void ins(int u,int x){
		B[u] = x; 
		set<int>&s = st[lower_bound(sb+1,sb+1+sb[0],B[u])-sb];
		set<int>::iterator it = s.insert(u).first , it2 = it;
		if(it == s.begin()) 
			Add(0,u,1,B[u]);
		else 
			it--,Add(*it,u,1,B[u]),it++;
		if((++it2) != s.end()){
			Add(u,*it2,1,B[u]);
			if(it == s.begin()) 
				Add(0,*it2,-1,B[u]);
			else 
				it--,Add(*it,*it2,-1,B[u]),it++;
		}
	}
	
	void solve(){
		rep(i,1,N) if(B[i] != -1) ins(i,B[i]);
		rep(i,1,q) if(dat[i][0] == 1 || dat[i][0] == 5){
			for(int u=dat[i][2];u;u-=u&-u)
				Q[u].pb(mp(i,0));
		}
		else{
			if(dat[i][0] == 3) del(dat[i][1]);
			if(dat[i][0] == 2) del(dat[i][1]) , ins(dat[i][1] , dat[i][2]);
			if(dat[i][0] == 4) del(dat[i][1]) , ins(dat[i][1] , dat[i][2]);
		}
		
		rep(i,1,N){
			++tim;
			for(auto u:Q[i]){
				if(u.second == 0){
					rep(j,0,3) add(ans[u.first][j] , qry(dat[u.first][1],tr[j]));
				}
				else{
					int v = 1;
					if(u.second < 0) v = mod-1 , u.second = -u.second;
					rep(j,0,3){
						upd(u.first,v,tr[j]);
						v = 1ll * v * u.second % mod;
					}
				}
			}
		}
		rep(i,1,q) if(dat[i][0] == 1 || dat[i][0] == 5){
			if(dat[i][0] == 5) printf("%d\n",ans[i][0]);
			else {
				printf("%d\n",(((ans[i][1]*1ll*ans[i][1]%mod*ans[i][1])+2ll*ans[i][3]-3ll*ans[i][2]*ans[i][1])%mod*iv6%mod+mod)%mod);
			}
		}
	}
}

namespace Treap{
	int sz[maxn],key[maxn],lc[maxn],rc[maxn],sm[maxn],val[maxn],rk[maxn],rt,tot;
	void upd(int u){ sz[u] = sz[lc[u]] + sz[rc[u]] + 1 , sm[u] = sm[lc[u]] + sm[rc[u]] + val[u]; }
	void merge(int &u,int l,int r){
		if(!l || !r) return (void)(u = l+r);
		if(key[l] < key[r]) u = l , merge(rc[u] , rc[l] , r);
		else u = r , merge(lc[u] , l , lc[r]);
		upd(u);
	}
	void split_sz(int u,int &l,int &r,int rk){
		if(!u) return (void)( l = r = 0);
		if(sz[lc[u]] + 1 <= rk) l = u , split_sz(rc[u],rc[l],r,rk - sz[lc[u]]-1);
		else r = u , split_sz(lc[u],l,lc[r],rk);
		upd(u);
	}
	void split_sm(int u,int &l,int &r,int rk){
		if(!u) return (void)( l = r = 0);
		if(sm[lc[u]] + val[u] <= rk) l = u , split_sm(rc[u],rc[l],r,rk - sm[lc[u]] - val[u]);
		else r = u , split_sm(lc[u],l,lc[r],rk);
		upd(u);
	}
	int getpt(int x){
		int a,b,c;
		split_sm(rt,a,b,x-1);
		split_sz(b,b,c,1);
		int r = b;
		merge(rt,a,b) , merge(rt,rt,c);
		return r;
	}
	void dfs(int u){
		if(!u) return;
		static int tim = 0;
		dfs(lc[u]);
		rk[u] = ++tim;
		dfs(rc[u]);
	}
	void solve(){
		rep(i,1,n) val[i] = sz[i] = sm[i] = 1 , key[i] = rand() , merge(rt,rt,i);
		tot = n;
		rep(i,1,q){
			int a,b,c,d;
			read(dat[i][0]),read(dat[i][1]);
			if(dat[i][0] == 3){
				split_sm(rt,a,b,dat[i][1]-1);
				split_sz(b,b,c,1);
				val[b] = sm[b] = 0;
				dat[i][1] = b;
				merge(rt,a,b) , merge(rt,rt,c);
				continue;
			}
			read(dat[i][2]);
			if(dat[i][0] == 1 || dat[i][0] == 5){
				dat[i][1] = getpt(dat[i][1]);
				dat[i][2] = getpt(dat[i][2]);
			}
			if(dat[i][0] == 2){
				dat[i][1] = getpt(dat[i][1]);
			}
			if(dat[i][0] == 4){
				split_sm(rt,a,b,dat[i][1]);
				dat[i][1] = ++tot;
				key[tot] = rand() , sm[tot] = sz[tot] = val[tot] = 1;
				merge(rt,a,tot) , merge(rt,rt,b);
			}
		}
		dfs(rt);
		rep(i,1,q){
			if(dat[i][0] == 1 || dat[i][0] == 5)
				dat[i][1] = rk[dat[i][1]] , dat[i][2] = rk[dat[i][2]];
			else dat[i][1] = rk[dat[i][1]];
		}
		memset(B,-1,sizeof B);
		rep(i,1,n) B[rk[i]] = A[i];
		N = tot;
	}
}

char End;

int main(){
	read(n),read(q);
	
	rep(i,1,n) read(A[i]);
	Treap::solve();
	rep(i,1,n) sb[++sb[0]] = A[i];
	rep(i,1,q) if(dat[i][0] == 2 || dat[i][0] == 4)
		sb[++sb[0]] = dat[i][2];
	sort(sb+1,sb+1+sb[0]);
	sb[0] = unique(sb+1,sb+1+sb[0]) - sb - 1;
	BIT::solve();
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/107619132