玄关求调
查看原帖
玄关求调
747421
qinhuanmma楼主2024/6/1 16:59

写了一天了,对拍总是和正确答案差一点,现在只想保证正确性,卡常后面再说。

#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define M 500
namespace fast_IO{
	#define FASTIO
	#define IOSIZE 100000
	char ibuf[IOSIZE],obuf[IOSIZE];char*p1=ibuf,*p2=ibuf,*p3=obuf;
	#ifdef ONLINE_JUDGE
	#define getchar()((p1==p2)and(p2=(p1=ibuf)+fread(ibuf,1,IOSIZE,stdin),p1==p2)?(EOF):(*p1++))
	#define putchar(x)((p3==obuf+IOSIZE)&&(fwrite(obuf,p3-obuf,1,stdout),p3=obuf),*p3++=x)
	#endif
	#define isdigit(ch)(ch>47&&ch<58)
	#define isspace(ch)(ch<33)
	template<typename T>inline T read(){T s=0;int w=1;char ch;while(ch=getchar(),!isdigit(ch)and(ch!=EOF))if(ch=='-')w=-1;if(ch==EOF)return false;while(isdigit(ch))s=s*10+ch-48,ch=getchar();return s*w;}template<typename T>inline bool read(T&s){s=0;int w=1;char ch;while(ch=getchar(),!isdigit(ch)and(ch!=EOF))if(ch=='-')w=-1;if(ch==EOF)return false;while(isdigit(ch))s=s*10+ch-48,ch=getchar();return s*=w,true;}inline bool read(char&s){while(s=getchar(),isspace(s));return true;}inline bool read(char*s){char ch;while(ch=getchar(),isspace(ch));if(ch==EOF)return false;while(!isspace(ch))*s++=ch,ch=getchar();*s='\000';return true;}template<typename T>inline void print(T x){if(x<0)putchar('-'),x=-x;if(x>9)print(x/10);putchar(x%10+48);}inline void print(char x){putchar(x);}inline void print(char*x){while(*x)putchar(*x++);}inline void print(const char*x){for(int i=0;x[i];i++)putchar(x[i]);}
	#ifdef _GLIBCXX_STRING
	inline bool read(std::string&s){s="";char ch;while(ch=getchar(),isspace(ch));if(ch==EOF)return false;while(!isspace(ch))s+=ch,ch=getchar();return true;}inline void print(std::string x){for(int i=0,n=x.size();i<n;i++)putchar(x[i]);}
	#endif
	template<typename T,typename...T1>inline int read(T&a,T1&...other){return read(a)+read(other...);}template<typename T,typename...T1>inline void print(T a,T1...other){print(a);print(other...);}struct Fast_IO{~Fast_IO(){fwrite(obuf,p3-obuf,1,stdout);}}io;template<typename T>Fast_IO&operator>>(Fast_IO&io,T&b){return read(b),io;}template<typename T>Fast_IO&operator<<(Fast_IO&io,T b){return print(b),io;}
}using namespace fast_IO;
#define cin io
#define cout io
#define endl '\n'
namespace cza{
	int n, m, B, lb;
	int a[N];
	int kuai[N], lft[N], rit[N];   //分块 
	int bcnt[M][M], cnt[M][N];     //前i个块中有多少个在第j个值域块中的 / 前i个块中有多少个值为j的 
	int fa[N], v[M][N], re[M][N];  //并查集,v表示第i个块中j对应的值,re表示第i个块中值为j的是谁 
	int get_fa(int u){
		return fa[u] == u ? u : fa[u] = get_fa(fa[u]); 
	}
	void merge(int p, int u, int vv){
		u = get_fa(u), vv = get_fa(vv);
		fa[u] = vv;
		re[p][v[p][u]] = 0;
		v[p][u] = 0;
	}
	void init(){
		B = 420;
		for(int i = 1; i <= N - 10; i++) kuai[i] = (i - 1) / B + 1;
		lb = kuai[N - 10];
		for(int i = 1; i <= lb; i++) lft[i] = rit[i - 1] + 1, rit[i] = i * B;
		rit[lb] = n;
		for(int i = 1; i <= n; i++){
			bcnt[kuai[i]][kuai[a[i]]]++;
			cnt[kuai[i]][a[i]]++;
		}
		for(int i = 1; i <= lb; i++){
			for(int j = 1; j <= lb; j++){
				bcnt[i][j] += bcnt[i - 1][j];
			}
		}
		for(int i = 1; i <= lb; i++){
			for(int j = 1; j <= N - 10; j++){
				cnt[i][j] += cnt[i - 1][j];
			}
		}
		vector<int> tmp;
		for(int i = 1; i <= lb; i++){
			tmp. resize(N);
			tmp. clear();
			for(int j = lft[i]; j <= rit[i]; j++){
				fa[j] = j;
				if(!tmp[a[j]]){
					tmp[a[j]] = j;
					v[i][j] = a[j];
					re[i][a[j]] = j;
				}else{
					merge(i, j, tmp[a[j]]);
				}
			}
		}
	}//预处理 
	void remod(int p){
		for(int i = lft[p]; i <= rit[p]; i++){
			a[i] = v[p][get_fa(i)];
		}//将p块的a数组重新赋值正确 
	}
	void rebuild(int p){
		vector<int> tmp;
		tmp. resize(N);
		tmp. clear();
		for(int j = lft[p]; j <= rit[p]; j++){
			fa[j] = j;
			if(!tmp[a[j]]){
				tmp[a[j]] = j;
				v[p][j] = a[j];
				re[p][a[j]] = j;
			}else{
				merge(p, j, tmp[a[j]]);
			}
		}
	}//重构p块的并查集 
	void change(int l, int r, int x, int y){
		if(x == y) return ;
		int bl = kuai[l], br = kuai[r];
		if(bl == br){
			remod(bl);
			int der = 0;
			for(int i = l; i <= r; i++){
				if(a[i] == x) a[i] = y, der++;
			}
			rebuild(bl);
			for(int i = bl; i <= lb; i++){
				cnt[i][x] -= der;
				cnt[i][y] += der;
				bcnt[i][kuai[x]] -= der;
				bcnt[i][kuai[y]] += der;
			}
			return ;
		}
		remod(bl);
		int der1 = 0;
		for(int i = l; i <= rit[bl]; i++){
			if(a[i] == x) a[i] = y, der1++;
		}
		rebuild(bl);
		remod(br);
		int der2 = 0;
		for(int i = lft[br]; i <= r; i++){
			if(a[i] == x) a[i] = y, der2++;
		}
		rebuild(br);
		for(int i = bl + 1; i < br; i++){
			if(!re[i][x]) continue;
			if(!re[i][y]){
				re[i][y] = re[i][x];
				re[i][x] = 0;
				v[i][re[i][y]] = y; 
			}else{
				merge(i, re[i][x], re[i][y]);
			}
		}
		int der = 0, last = cnt[bl - 1][x];
		for(int i = bl; i <= lb; i++){
			if(i == bl) der += der1;
			else if(i == br) der += der2;
			else if(bl < i and i < br) der += cnt[i][x] - last;
			last = cnt[i][x];
			cnt[i][x] -= der;
			cnt[i][y] += der;
			bcnt[i][kuai[x]] -= der;
			bcnt[i][kuai[y]] += der;
		}//更新 bcnt cnt 
	}
	int R(int p, int x){
		return v[p][get_fa(x)];
	}//x位置的真实值 
	int get_ans(int l, int r, int k){
		int bl = kuai[l], br = kuai[r];
		vector<int> tmp;
		tmp. resize(N);
		tmp. clear();
		vector<int> btmp;
		btmp. resize(N);
		btmp. clear();
		if(bl == br){
			for(int i = l; i <= r; i++){
				tmp[R(bl, i)]++;
				btmp[kuai[R(bl, i)]]++;
			}
			int now = 1;
			int der = btmp[1];
			while(k > der) k -= der, now++, der = btmp[now];
			now = lft[now];
			der = tmp[now];
			while(k > der) k -= der, now++, der = tmp[now];
			return now;
		}
		for(int i = l; i <= rit[bl]; i++){
			tmp[R(bl, i)]++;
			btmp[kuai[R(bl, i)]]++;
		}
		for(int i = lft[br]; i <= r; i++){
			tmp[R(br, i)]++;
			btmp[kuai[R(br, i)]]++;
		}
		int now = 1;
		int der = btmp[now] + bcnt[br - 1][now] - bcnt[bl][now];
		while(k > der) k -= der, now++, der = btmp[now] + bcnt[br - 1][now] - bcnt[bl][now];
		now = lft[now];
		der = tmp[now] + cnt[br - 1][now] - cnt[bl][now];
		while(k > der) k -= der, now++, der = tmp[now] + cnt[br - 1][now] - cnt[bl][now];
		return now;
	}
	int main(){
		cin >> n >> m;
		for(int i = 1; i <= n; i++){
			cin >> a[i];
		}
		init();
		for(int i = 1; i <= m; i++){
			int op, l, r, x, y;
			cin >> op >> l >> r;
			if(op == 1){
				cin >> x >> y;
				change(l, r, x, y);
			}else{
				cin >> x;
				cout << get_ans(l, r, x) << '\n';
			}
		}
		return 0;
	}
}
signed main(){
	return cza::main();
}

代码写得很史
谁来救救我

2024/6/1 16:59
加载中...