求助

P1197 [JSOI2008] 星球大战

presucc @ 2019-05-13 22:54:36

一道并查集的题我偏是用了lct……

WA40,求指点

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=500050;
int ch[maxn][2],par[maxn],rev[maxn],sum[maxn],val[maxn],sta[maxn];
int que[maxn],mark[maxn],ans[maxn],head[maxn],tot,len;
vector<int> vv[maxn];
struct edge
{
    int to,nxt,from;
}e[maxn];
void add(int x,int y)
{
    e[++tot].to=y;
    e[tot].nxt=head[x];
    e[tot].from=x;
    head[x]=tot;
}
bool chk(int x)
{
    return ch[par[x]][0]==x||ch[par[x]][1]==x;
}
void update(int x)
{
    sum[x]=sum[ch[x][0]]^sum[ch[x][1]]^val[x];
}
void reverse(int x)
{
    swap(ch[x][0],ch[x][1]);
    rev[x]^=1; 
}
void pushdown(int x)
{
    if (rev[x])
    {
        reverse(ch[x][0]);
        reverse(ch[x][1]);
        rev[x]=0;
    }
}
void rotate(int x)
{
    int y=par[x],z=par[y],k=(ch[y][1]==x),w=ch[x][k^1];
    if (chk(y)) ch[z][ch[z][1]==y]=x;
    ch[x][k^1]=y,ch[y][k]=w;
    if (w) par[w]=y;
    par[y]=x,par[x]=z;
    update(x),update(y);
}
void splay(int x)
{
    int y=x,z=0;
    sta[++z]=y;
    while (chk(y)) sta[++z]=y=par[y];
    while (z) pushdown(sta[z--]);
    while (chk(x))
    {
        y=par[x],z=par[y];
        if (chk(y)) rotate((ch[y][0]==x)^(ch[z][0]==y)?x:y);
        rotate(x);
    }
    update(x);
}
void access(int x)
{
    for (int y=0;x;x=par[y=x])
        splay(x),ch[x][1]=y,update(x);
}
void makeroot(int x)
{
    access(x),splay(x),reverse(x);
}
int findroot(int x)
{
    access(x),splay(x);
    while (ch[x][0]) pushdown(x),x=ch[x][0];
    return x;
}
void split(int x,int y)
{
    makeroot(x),access(y),splay(y);
}
void link(int x,int y)
{
    makeroot(x);
    if (findroot(y)!=x) par[x]=y;
}
void cut(int x,int y)
{
    split(x,y);
    if (findroot(y)==x&&par[x]==y&&!ch[x][1]) ch[y][0]=par[x]=0;
}
int n,m,x,y,ttt;
int main()
{
    scanf("%d%d",&n,&m);
    while (m--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x++,y++;
        add(x,y);add(y,x);
    }
    int q;
    scanf("%d",&q);
    ttt=n-q;
    for (int i=1;i<=q;i++)
        scanf("%d",&que[i]),que[i]++,mark[que[i]]=1;
    for (int i=1;i<=2*m;i++)
    {
        if (!mark[e[i].from]&&!mark[e[i].to]&&findroot(e[i].from)!=findroot(e[i].to))
        {
            link(e[i].from,e[i].to);
            ttt--;
        }
    }
    ans[q+1]=ttt;
    for (int i=q;i>=1;i--)
    {
        int x=que[i];
        ttt++;
        mark[x]=false;
        for (int j=head[x];j;j=e[j].nxt)
        {
            int tr=e[j].to;
            if (!mark[tr]&&findroot(e[j].from)!=findroot(tr))
            {
                ttt--;
                link(e[j].from,tr);
            }
        }
        ans[i]=ttt;
    }
    for (int i=1;i<=q+1;i++) printf("%d\n",ans[i]);
    return 0;
}

by Metheus @ 2019-05-14 09:53:59

pushdown写错了


by Metheus @ 2019-05-14 09:54:43

对不起看错了(雾)


|