BZOJ1095/ZJOI2007/捉迷藏

Posted on By 二价氢

膜拜了一下午某岛的东西,然后恍然大悟,原来还能这么做!

速度还是很快的2333

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
const int maxn=100005;
const int head=-1,tail=-2,inf=674275764;
vector <int> e[maxn];
typedef vector <int>::iterator ii;
int seq[maxn*6],pos[maxn*2],color[maxn*2],vis[maxn*2],cnt;
int dark;
int n,m;
char op[6];
int tu,tv;
//-- tree
struct seg_tree{
    int l,r,dist;
    int r_p,r_m,l_p,l_m;
    void set(int p)
    {
        l=(seq[p]==head);
        r=(seq[p]==tail);
        dist=-inf;
        l_p=l_m=r_p=r_m=
            (seq[p]>=0 && color[seq[p]]==0)?0:-inf;
    }
}t[maxn*12];
void update(int x)
{
    t[x].l=t[x*2+1].l+max(t[x*2].l-t[x*2+1].r,0);
    t[x].r=t[x*2].r+max(t[x*2+1].r-t[x*2].l,0);
    t[x].dist=max(max(t[x*2].dist,t[x*2+1].dist),max(t[x*2].r_p+t[x*2+1].l_m,t[x*2].r_m+t[x*2+1].l_p));
    t[x].l_p=max(max(t[x*2+1].l_p+t[x*2].r-t[x*2].l,t[x*2+1].l_m+t[x*2].r+t[x*2].l),t[x*2].l_p);
    t[x].l_m=max(t[x*2].l_m,t[x*2+1].l_m-t[x*2].r+t[x*2].l);
    t[x].r_p=max(max(t[x*2].r_p-t[x*2+1].r+t[x*2+1].l,t[x*2].r_m+t[x*2+1].r+t[x*2+1].l),t[x*2+1].r_p);
    t[x].r_m=max(t[x*2+1].r_m,t[x*2].r_m+t[x*2+1].r-t[x*2+1].l);
}
void build(int x,int l,int r)
{
    if (l==r)
    {
        t[x].set(l);
        return;
    }
    int mid=(l+r)/2;
    build(x*2,l,mid);build(x*2+1,mid+1,r);
    update(x);
}
void edit(int x,int l,int r,int p)
{
    if (l==r)
    {
        t[x].set(l);
        return;
    }
    int mid=(l+r)/2;
    if (p<=mid)
        edit(x*2,l,mid,p);
    else
        edit(x*2+1,mid+1,r,p);
    update(x);
}
void dfs(int x)
{
    vis[x]=true;
    seq[++cnt]=head;
    pos[x]=++cnt;
    seq[cnt]=x;
    for (ii j=e[x].begin();j!=e[x].end();j++)
        if (!vis[*j])
            dfs(*j);
    seq[++cnt]=tail;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        scanf("%d%d",&tu,&tv);
        e[tu].push_back(tv);
        e[tv].push_back(tu);
    }
    dark=n;
    dfs(1);
    build(1,1,cnt);
    scanf("%d",&m);
    while (m--)
    {
        scanf("%s",op);
        if (op[0]=='G')
        {
            if (dark==0)
                printf("-1\n");
            else if (dark==1)
                printf("0\n");
            else
                printf("%d\n",t[1].dist);
        }
        else
        {
            scanf("%d\n",&tu);
            color[tu]=1-color[tu];
            dark+=(color[tu])?(-1):(1);
            edit(1,1,cnt,pos[tu]);
        }
    }
    return 0;
}