【BZOJ1125】[POI2008]Poc
Description
n列火车,每条有l节车厢。每节车厢有一种颜色(用小写字母表示)。有m次车厢交换操作。求:对于每列火车,在交换车厢的某个时刻,与其颜色完全相同的火车最多有多少。
Input
n l m (2 ≤ n ≤ 1000, 1 ≤ l ≤ 100, 0 ≤ m ≤ 100000) n行字符串,长度为l m行,每行4个数a b c d,a车的第b个字符与c车第d个字符交换。
Output
n个数,在交换车厢的某个时刻,与该车颜色完全相同的火车最多数目。
Sample Input
5 6 7
ababbd
abbbbd
aaabad
caabbd
cabaad
2 3 5 4
5 3 5 5
3 5 2 2
1 2 4 3
2 2 5 1
1 1 3 3
4 1 5 6
ababbd
abbbbd
aaabad
caabbd
cabaad
2 3 5 4
5 3 5 5
3 5 2 2
1 2 4 3
2 2 5 1
1 1 3 3
4 1 5 6
Sample Output
3
3
3
2
3
3
3
2
3
题解:考虑将hash值相同的都放到同一棵平衡树中(可以用map维护平衡树的root)。这样删除和插入都比较容易,每次加入的时候都给平衡树的整体打一个最大值标记即可。
注意a=c的情况。
#include <cstdio> #include <cstring> #include <iostream> #include <map> using namespace std; typedef unsigned long long ll; int n,len,m,ret; char str[1010][110]; struct node { int siz,ch[2],tag,org; }s[1010]; ll bas[110],hs[1010]; int ans[1010]; map<ll,int> rt; void pushup(int x) { s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1; } void updata(int x,int val) {ans[s[x].org]=max(ans[s[x].org],val),s[x].tag=max(s[x].tag,val);} void pushdown(int x) { if(s[x].tag) { if(s[x].ch[0]) updata(s[x].ch[0],s[x].tag); if(s[x].ch[1]) updata(s[x].ch[1],s[x].tag); s[x].tag=0; } } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f; } void rotate(int &x,int d) { int y=s[x].ch[d]; pushdown(x),pushdown(y); s[x].ch[d]=s[y].ch[d^1],s[y].ch[d^1]=x; pushup(x),pushup(y); x=y; } void maintain(int &x,int d) { if(s[s[s[x].ch[d]].ch[d]].siz>s[s[x].ch[d^1]].siz) rotate(x,d); else if(s[s[s[x].ch[d]].ch[d^1]].siz>s[s[x].ch[d^1]].siz) rotate(s[x].ch[d],d^1),rotate(x,d); else return ; maintain(s[x].ch[d],d),maintain(s[x].ch[d^1],d^1); maintain(x,d),maintain(x,d^1); } void insert(int &x,int y) { if(!x) { x=y,s[x].ch[0]=s[x].ch[1]=0,s[x].siz=1,s[x].tag=0; return ; } pushdown(x); int d=(s[y].org>s[x].org); insert(s[x].ch[d],y),s[x].siz++; maintain(x,d); } void del(int &x,int y) { s[x].siz--,pushdown(x); if(y>s[x].org) del(s[x].ch[1],y); else if(y<s[x].org) del(s[x].ch[0],y); else { if(!s[x].ch[0]||!s[x].ch[1]) ret=x,x=s[x].ch[0]^s[x].ch[1]; else { int u=s[x].ch[1]; pushdown(u); while(s[u].ch[0]) u=s[u].ch[0],pushdown(u); s[x].org=s[u].org; del(s[x].ch[1],s[u].org); } } } int main() { n=rd(),len=rd(),m=rd(); int i,j,a,b,c,d,ra,rb; for(bas[0]=1,i=1;i<=len;i++) bas[i]=bas[i-1]*131; for(i=1;i<=n;i++) { scanf("%s",str[i]+1); for(j=1;j<=len;j++) hs[i]=hs[i]*131+str[i][j]; s[i].org=i,insert(rt[hs[i]],i),updata(rt[hs[i]],s[rt[hs[i]]].siz); } for(i=1;i<=m;i++) { a=rd(),b=rd(),c=rd(),d=rd(); if(a==c) { del(rt[hs[a]],a),s[ret].org=a; hs[a]+=(str[a][d]-str[a][b])*bas[len-b]; hs[a]+=(str[a][b]-str[a][d])*bas[len-d]; insert(rt[hs[a]],ret),updata(rt[hs[a]],s[rt[hs[a]]].siz); swap(str[a][b],str[a][d]); continue; } del(rt[hs[a]],a),s[ret].org=a,ra=ret; del(rt[hs[c]],c),s[ret].org=c,rb=ret; hs[a]+=(str[c][d]-str[a][b])*bas[len-b]; hs[c]+=(str[a][b]-str[c][d])*bas[len-d]; insert(rt[hs[a]],ra),updata(rt[hs[a]],s[rt[hs[a]]].siz); insert(rt[hs[c]],rb),updata(rt[hs[c]],s[rt[hs[c]]].siz); swap(str[a][b],str[c][d]); } for(i=1;i<=n;i++) del(rt[hs[i]],i); for(i=1;i<=n;i++) printf("%d ",ans[i]); return 0; }//5 6 7 ababbd abbbbd aaabad caabbd cabaad 2 3 5 4 5 3 5 5 3 5 2 2 1 2 4 3 2 2 5 1 1 1 3 3 4 1 5 6