[bzoj1125][動態開點線段樹][雜湊]Poc
阿新 • • 發佈:2018-12-15
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
Sample Output
3
3
3
2
3
題解
開1000棵線段樹維護一下雜湊值
然後你就發現不同雜湊值總共不會超過10W個
開個vector記錄一下每個串變成了什麼雜湊值,在什麼時候變成的
動態開點線段樹記錄這個雜湊值在這裡開始是這一個值,直到碰到下一個值之前都還是這個值
最後掃一遍就行了…
//#orz tyb
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define ULL unsigned long long
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const LL mod=1e9+7;
const ULL base=233;
ULL temp[2100];
int ma[2005][105];
struct segtree1
{
ULL mx[1100][110*8];
void modify(int now,int l,int r,int p,int c,int op)
{
// if(l==r){mx[op][now]=c%mod;return ;}
if(l==r){mx[op][now]=c;return ;}
int mid=(l+r)/2,lc=now<<1,rc=now<<1|1;
if(p<=mid)modify(lc,l,mid,p,c,op);
else modify(rc,mid+1,r,p,c,op);
// mx[op][now]=(mx[op][lc]*temp[r-mid+1]%mod+mx[op][rc])%mod;
mx[op][now]=mx[op][lc]*temp[r-mid]+mx[op][rc];
}
void buildtree(int now,int l,int r,int op)
{
if(l==r){mx[op][now]=ma[op][l]%mod;return ;}
int mid=(l+r)/2,lc=now<<1,rc=now<<1|1;
buildtree(lc,l,mid,op);buildtree(rc,mid+1,r,op);
// mx[op][now]=(mx[op][lc]*temp[r-mid+1]%mod+mx[op][rc])%mod;
mx[op][now]=mx[op][lc]*temp[r-mid]+mx[op][rc];
}
}seg1;
map<ULL,int> mp;
map<ULL,int> rt;
struct segtree2
{
int lc[210000*30],rc[210000*30],mx[210000*30],trlen;
void modify(int &now,int l,int r,int p,int c)
{
if(!now)now=++trlen;
if(l==r){mx[now]=c;return ;}
int mid=(l+r)/2;
if(p<=mid)modify(lc[now],l,mid,p,c);
else modify(rc[now],mid+1,r,p,c);
mx[now]=max(mx[lc[now]],mx[rc[now]]);
}
int query(int now,int l,int r,int ql,int qr)
{
if(!now)return 0;
if(l>=ql&&r<=qr)return mx[now];
int mid=(l+r)/2;
if(qr<=mid)return query(lc[now],l,mid,ql,qr);
else if(mid+1<=ql)return query(rc[now],mid+1,r,ql,qr);
else return max(query(lc[now],l,mid,ql,mid),query(rc[now],mid+1,r,mid+1,qr));
}
}seg2;
int n,L,m;
vector<pair<ULL,int> > vec[1005];
char ch[1005];
int answer[1005];
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
temp[0]=1;for(int i=1;i<=2000;i++)temp[i]=temp[i-1]*base;
n=read();L=read();m=read();
for(int i=1;i<=n;i++)
{
scanf("%s",ch+1);
for(int j=1;j<=L;j++)ma[i][j]=ch[j]-'a'+1;
seg1.buildtree(1,1,L,i);
vec[i].push_back(mp(seg1.mx[i][1],1));
}
for(int i=1;i<=n;i++)mp[seg1.mx[i][1]]++;
for(int i=1;i<=n;i++)seg2.modify(rt[seg1.mx[i][1]],1,m,1,mp[seg1.mx[i][1]]);
// printf("%d CHECKER \n",0);
// for(int i=1;i<=n;i++)printf("id= %d hash=%llu sum= %d\n",i,seg1.mx[i][1],mp[seg1.mx[i][1]]);
// for(int i=1;i<=n;i++)answer[i]=max(answer[i],mp[seg1.mx[i][1]]);
for(int tt=1;tt<=m;tt++)
{
int a=read(),b=read(),c=read(),d=read();
mp[seg1.mx[a][1]]--;
if(a!=c)mp[seg1.mx[c][1]]--;
seg2.modify(rt[seg1.mx[a][1]],1,m,tt,mp[seg1.mx[a][1]]);
seg2.modify(rt[seg1.mx[c][1]],1,m,tt,mp[seg1.mx[c][1]]);
seg1.modify(1,1,L,b,ma[c][d],a);seg1.modify(1,1,L,d,ma[a][b],c);
mp[seg1.mx[a][1]]++;
if(a!=c)mp[seg1.mx[c][1]]++;
// printf("%d CHECKER \n",tt);
// for(int i=1;i<=n;i++)printf("id= %d hash=%llu sum= %d\n",i,seg1.mx[i][1],mp[seg1.mx[i][1]]);
// for(int i=1;i<=n;i++)answer[i]=max(answer[i],mp[seg1.mx[i][1]]);
seg2.modify(rt[seg1.mx[a][1]],1,m,tt,mp[seg1.mx[a][1]]);
seg2.modify(rt[seg1.mx[c][1]],1,m,tt,mp[seg1.mx[c][1]]);
swap(ma[a][b],ma[c][d]);
vec[a].push_back(mp(seg1.mx[a][1],tt));
if(a!=c)vec[c].push_back(mp(seg1.mx[c][1],tt));
}
for(int i=1;i<=n;i++)
{
int ln=vec[i].size();
for(int j=0;j<ln;j++)
{
int st=vec[i][j].second,ed;ULL pa=vec[i][j].first;
if(j==ln-1)ed=m;
else ed=vec[i][j+1].second-1;
answer[i]=max(answer[i],seg2.query(rt[pa],1,m,st,ed));
}
}
for(int i=1;i<=n;i++)pr2(answer[i]);
return 0;
}