BZOJ 2908 又是nand

Posted on 2017-02-21 16:59  ziliuziliu  阅读(234)  评论(0编辑  收藏  举报

我的方法是处理每个区间输入0,1,输出多少。这个方法适用于任何数据。。。比如直接给你真值表那种。

还有一种方法是发现0,1 nand 0 都是1,于是需要维护从这个点向上有多少个连续的1。貌似不好写。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 100050
#define maxe 200050
using namespace std;
long long n,m,k,a[maxv],x,y,g[maxv],nume=1,top[maxv],fath[maxv],w[maxv],dis[maxv],size[maxv],son[maxv],times=0,fw[maxv];
long long ls[maxv<<2],rs[maxv<<2],root,tot=0;
long long bit[50],ret[50],tops=0;
bool aft[maxv<<2][2][32][2];
char type[20];
struct edge
{
    long long v,nxt;
}e[maxe];
struct seg
{
    long long type,l,r;
    seg (long long type,long long l,long long r):type(type),l(l),r(r) {}
    seg () {}
}s[maxv];
bool cmp(seg x,seg y)
{
    if (x.type!=y.type) return x.type<y.type;
    if (x.type==1) return dis[fw[x.l]]>dis[fw[y.l]];
    else return dis[fw[x.l]]<dis[fw[y.l]];
}
int read()
{ 
    char ch;long long data=0;
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9')
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data;
}
void addedge(long long u,long long v)
{
    e[++nume].v=v;e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs1(long long x)
{
    size[x]=1;son[x]=0;
    for (int i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if (v!=fath[x])
        {
            fath[v]=x;dis[v]=dis[x]+1;
            dfs1(v);
            size[x]+=size[v];
            if (size[v]>size[son[x]]) son[x]=v;
        }
    }
}
void dfs2(long long x,long long father)
{
    w[x]=++times;fw[times]=x;top[x]=father;
    if (son[x]) dfs2(son[x],father);
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if ((v!=son[x]) && (v!=fath[x]))
            dfs2(v,v);
    }
}
void merge(long long now)
{
    for (long long i=0;i<k;i++)
    {
        aft[now][0][i][0]=aft[rs[now]][aft[ls[now]][0][i][0]][i][0];
        aft[now][1][i][0]=aft[rs[now]][aft[ls[now]][1][i][0]][i][0];
        aft[now][0][i][1]=aft[ls[now]][aft[rs[now]][0][i][1]][i][1];
        aft[now][1][i][1]=aft[ls[now]][aft[rs[now]][1][i][1]][i][1];
    }
}
void build(long long &now,long long left,long long right)
{
    now=++tot;
    if (left==right)
    {
        for (long long i=0;i<k;i++) bit[i]=a[fw[left]]&(1LL<<i);
        for (long long i=0;i<k;i++)
        {
             if (bit[i]) aft[now][0][i][0]=aft[now][0][i][1]=1,aft[now][1][i][0]=aft[now][1][i][1]=0;
             else aft[now][0][i][0]=aft[now][0][i][1]=aft[now][1][i][0]=aft[now][1][i][1]=1;
        }
        return;
    }
    long long mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    merge(now);
}
void modify(long long now,long long left,long long right,long long pos)
{
    if (left==right)
    {
        for (long long i=0;i<k;i++) bit[i]=a[fw[left]]&(1LL<<i);
        for (long long i=0;i<k;i++)
        {
             if (bit[i]) aft[now][0][i][0]=aft[now][0][i][1]=1,aft[now][1][i][0]=aft[now][1][i][1]=0;
             else aft[now][0][i][0]=aft[now][0][i][1]=aft[now][1][i][0]=aft[now][1][i][1]=1;
        }
        return;
    }
    long long mid=(left+right)>>1;
    if (pos<=mid) modify(ls[now],left,mid,pos);
    else modify(rs[now],mid+1,right,pos);
    merge(now);
}
void ask(long long now,long long left,long long right,long long l,long long r,long long type)
{
    if (left==l && right==r)
    {
        for (long long i=0;i<k;i++)
            ret[i]=aft[now][ret[i]][i][(type-1)^1];
        return;
    }
    long long mid=(left+right)>>1;
    if (r<=mid) ask(ls[now],left,mid,l,r,type);
    else if (l>=mid+1) ask(rs[now],mid+1,right,l,r,type);
    else 
    {
        if (type==1) ask(rs[now],mid+1,right,mid+1,r,type),ask(ls[now],left,mid,l,mid,type);
        else ask(ls[now],left,mid,l,mid,type),ask(rs[now],mid+1,right,mid+1,r,type);
    }
}
void work()
{
    for (long long i=0;i<k;i++) ret[i]=0;tops=0;
    long long f1=top[x],f2=top[y],flag=1;
    while (f1!=f2)
    {
        if (dis[f1]<dis[f2]) {swap(f1,f2);swap(x,y);flag=3-flag;}
        s[++tops]=seg(flag,w[f1],w[x]);
        x=fath[f1];f1=top[x];
    }
    if (dis[x]>dis[y]) {swap(x,y);flag=3-flag;}
    s[++tops]=seg(3-flag,w[x],w[y]);
    sort(s+1,s+tops+1,cmp);
    for (long long i=1;i<=tops;i++)
        ask(root,1,n,s[i].l,s[i].r,s[i].type);
    long long ans=0;
    for (long long i=k-1;i>=0;i--)
        ans+=ret[i]*(1LL<<i);
    printf("%lld\n",ans);
}
int main()
{
    n=read();m=read();k=read();
    for (long long i=1;i<=n;i++) a[i]=read();
    for (long long i=1;i<=n-1;i++)
    {
        x=read();y=read();
        addedge(x,y);addedge(y,x);
    }
    dfs1(1);
    dfs2(1,1);
    build(root,1,n);
    for (long long i=1;i<=m;i++)
    {
        scanf("%s",type);
        if (type[0]=='R')
        {
            x=read();y=read();
            a[x]=y;modify(root,1,n,w[x]);
        }
        else
        {
            x=read();y=read();
            work();
        }
    }
    return 0;
}