[HDU5997] [BestCoder Round #90] rausen loves cakes启发式合并+线段树

来源:互联网 发布:淘宝怎么给客服发图片 编辑:程序博客网 时间:2024/06/11 18:34

诶手速慢了一两秒钟没了rank1
(为了速度借用了hzwer的板子,自己手写的线段树)
同BZOJ1483梦幻布丁,只是多一个区间l,r的询问
用线段树记录[l,r]区间内有多少个相同的布丁
答案等于qr-ql+1-([ql,qr]上相同的布丁)

#include<cstdio>#include<iostream>#include<cstring>#define N 100005#define M 1000005#define mid ((l+r)>>1)#define ls l,mid,(t<<1)#define rs mid+1,r,(t<<1^1)using namespace std;int n,m,cnt,ans;int c[N],nex[N],ft[M],head[M],s[M],st[M];int tr[4*N];int x,v;void update(int l,int r,int t) {    if (l>x || r<x) return ;    if (l == r) { tr[t] += v; return ; }    update(ls); update(rs); tr[t]=tr[2*t]+tr[2*t+1];}int ll,rr;void query(int l,int r,int t) {    if (l > rr || r < ll) return ;    if (l >= ll && r <= rr) { ans += tr[t]; return ; }    query(ls); query(rs);}void solve(int a,int b) {    for(int i=head[a];i;i=nex[i]) {        if(c[i+1]==b){ v=1; x=i; update(1,n,1); }        if(c[i-1]==b){ v=1; x=i-1; update(1,n,1); }    }    for(int i=head[a];i;i=nex[i])c[i]=b;    nex[st[a]]=head[b];head[b]=head[a];s[b]+=s[a];    head[a]=st[a]=s[a]=0;}void work(){    memset(tr,0,sizeof(tr));    memset(head,0,sizeof(head));    memset(nex,0,sizeof(nex));    memset(ft,0,sizeof(ft));    memset(st,0,sizeof(st));    memset(s,0,sizeof(s));    memset(c,0,sizeof(c));    cnt = ans = 0;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        scanf("%d",&c[i]);ft[c[i]]=c[i];        if(c[i]==c[i-1]) {            v=1; x=i-1; update(1,n,1);         }        if(!head[c[i]])st[c[i]]=i;        s[c[i]]++;nex[i]=head[c[i]];head[c[i]]=i;    }    for(int i=1;i<=m;i++)    {        int x,a,b,o;        scanf("%d",&x);        if(x==2) {            ans = 0;            scanf("%d%d",&ll,&rr);             o = rr-ll+1;            if (ll == rr) {                printf("1\n"); continue;            }            rr--;            query(1,n,1);            printf("%d\n",o-ans);        } else {            scanf("%d%d",&a,&b);            if(a==b)continue;            if(s[ft[a]]>s[ft[b]])                swap(ft[a],ft[b]);            a=ft[a];b=ft[b];            if(s[a]==0)continue;            s[b]+=s[a];s[a]=0;            solve(a,b);        }    }}int main(){    int T = 0; scanf("%d",&T);    while (T--) work();    return 0;}
1 0