zoukankan      html  css  js  c++  java
  • [BZOJ]2908: 又是nand

     题解:  LCT死于卡常....迫不得已写了树剖+线段树  思路很简单   按位分解 对于每一位  考虑这条路径上从右往左第一个0出现的位置   然后判断这一位经过这条路径后是0还是1  统计每一位贡献即可

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=1e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    
    int sum[MAXN<<2][33];
    ll a[MAXN];
    int k,n,m,fp[MAXN],p[MAXN];
    
    void up(int x){
        inc(i,0,k-1)sum[x][i]=sum[x<<1][i]+sum[x<<1|1][i];
    }
    
    void built(int x,int l,int r){
        if(l==r){
    	inc(i,0,k-1)sum[x][i]=((a[fp[l]]>>i)&1);
    	return ;
        }
        int mid=(l+r)>>1;
        built(x<<1,l,mid);
        built(x<<1|1,mid+1,r);
        up(x);
    }
    
    void update(int x,int l,int r,int t,int key){
        if(l==r){
    	inc(i,0,k-1)sum[x][i]=((key>>i)&1);
    	return ;
        }
        int mid=(l+r)>>1;
        if(t<=mid)update(x<<1,l,mid,t,key);
        else update(x<<1|1,mid+1,r,t,key);
        up(x);
    }
    
    int ans[33];
    void query1(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){
    	inc(i,0,k-1)ans[i]+=sum[x][i];
    	return ;
        }
        int mid=(l+r)>>1;
        if(ql<=mid)query1(x<<1,l,mid,ql,qr);
        if(qr>mid)query1(x<<1|1,mid+1,r,ql,qr);
    }
    
    int pos;
    void query2(int x,int l,int r,int ql,int qr,int id){
        if(pos)return ;
        if(ql<=l&&r<=qr){
    	if(sum[x][id]==r-l+1){return ;}
    	if(l==r){pos=l;return ;}
        }
        int mid=(l+r)>>1;
        if(qr>mid)query2(x<<1|1,mid+1,r,ql,qr,id);
        if(ql<=mid)query2(x<<1,l,mid,ql,qr,id);
    }
    
    void query3(int x,int l,int r,int ql,int qr,int id){
        if(pos)return ;
        if(ql<=l&&r<=qr){
    	if(sum[x][id]==r-l+1){return ;}
    	if(l==r){pos=l;return ;}
        }
        int mid=(l+r)>>1;
        if(ql<=mid)query3(x<<1,l,mid,ql,qr,id);
        if(qr>mid)query3(x<<1|1,mid+1,r,ql,qr,id);
    }
    
    
    int fa[MAXN],dep[MAXN],num[MAXN],son[MAXN];
    void dfs1(int x,int pre,int deep){
        fa[x]=pre;dep[x]=deep+1;num[x]=1;
        link(x){
    	if(j->t==pre)continue;
    	dfs1(j->t,x,deep+1);
    	num[x]+=num[j->t];
    	if(son[x]==-1||num[son[x]]<num[j->t])son[x]=j->t;
        }
    }
    
    int tp[MAXN],cnt;
    void dfs2(int x,int td){
        tp[x]=td;p[x]=++cnt;fp[p[x]]=x;
        if(son[x]!=-1)dfs2(son[x],td);
        link(x)if(j->t!=fa[x]&&j->t!=son[x])dfs2(j->t,j->t);
    }
    
    pii st[MAXN],ed[MAXN];int tot1,tot2;
    int vis[33];
    
    int Lca(int x,int y){
        int xx=tp[x];int yy=tp[y];
        while(xx!=yy){
    	if(dep[xx]<dep[yy])swap(xx,yy),swap(x,y);
    	x=fa[xx];xx=tp[x];
        }
        if(dep[x]>dep[y])swap(x,y);
        return x;
    }
    
    void solve(int u,int v){
        int y=v,x=u;
        inc(i,0,k-1)vis[i]=0;
        int uu=tp[u];int vv=tp[v];tot2=tot1=0;
        while(uu!=vv){
    	if(dep[uu]>dep[vv]){ed[++tot2]=mp(p[uu],p[u]);u=fa[uu];uu=tp[u];}
    	else {st[++tot1]=mp(p[vv],p[v]);v=fa[vv];vv=tp[v];}
        }
        if(dep[u]>dep[v])ed[++tot2]=mp(p[v],p[u]);
        else st[++tot1]=mp(p[u],p[v]);
        inc(i,1,tot1){
    	inc(j,0,k-1)ans[j]=0;
    	query1(1,1,n,st[i].first,st[i].second);
    	inc(j,0,k-1){
    	    if(vis[j])continue;
    	    if(ans[j]==st[i].second-st[i].first+1)continue;
    	    pos=0;
    	    query2(1,1,n,st[i].first,st[i].second,j);
    	    vis[j]=pos;
    	}
        }
        dec(i,tot2,1){
    	inc(j,0,k-1)ans[j]=0;
    	query1(1,1,n,ed[i].first,ed[i].second);
    	inc(j,0,k-1){
    	    if(vis[j])continue;
    	    if(ans[j]==ed[i].second-ed[i].first+1)continue;
    	    pos=0;
    	    query3(1,1,n,ed[i].first,ed[i].second,j);
    	    vis[j]=pos;
    	}
        }
        ll Sum=0;
        inc(i,0,k-1){
    	if(vis[i])u=fp[vis[i]];
    	else u=x; 
    	int lca=Lca(u,y);
    	int t=dep[u]+dep[y]-2*dep[lca]+1;
    	if((t&1))Sum+=(1ll<<i);
        }
        printf("%lld
    ",Sum);
    }
    
    int main(){
        n=read();m=read();k=read();
        inc(i,1,n)son[i]=-1,a[i]=read();
        int u,v;
        inc(i,2,n)u=read(),v=read(),add(u,v),add(v,u);
        char str[21];
        dfs1(1,0,0);dfs2(1,1);
        built(1,1,n);
        while(m--){
    	scanf("%s",str);u=read(),v=read();
    	if(str[0]=='R')update(1,1,n,p[u],v);
    	else solve(u,v);
        }
        return 0;
    }
    

      

    2908: 又是nand

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 557  Solved: 183
    [Submit][Status][Discuss]

    Description

    首先知道A nand B=not(A and B) (运算操作限制了数位位数为K)比如2 nand 3,K=3,则2 nand 3=not (2 and 3)=not 2=5。
    给出一棵树,树上每个点都有点权,定义树上从a到b的费用为0与路径上的点的权值顺次nand的结果,例如:从2号点到5号点顺次经过2->3->5,权值分别为5、7、2,K=3,那么最终结果为0 nand 5 nand 7 nand 2=7 nand 7 nand 2=0 nand 2=7,现在这棵树需要支持以下操作。
    ①    Replace a b:将点a(1≤a≤N)的权值改为b。
    ②    Query a b:输出点a到点b的费用。
    请众神给出一个程序支持这些操作。

    Input

    第一行N,M,K,树的节点数量、总操作个数和运算位数。
    接下来一行N个数字,依次表示节点i的权值。
    接下来N-1行,每行两个数字a,b(1≤a,b≤N)表示a,b间有一条树边。
    接下来M行,每行一个操作,为以上2类操作之一。
    N、M≤100000,K≤32

    Output

    对于操作②每个输出一行,如题目所述。

    Sample Input

    3 3 3
    2 7 3
    1 2
    2 3
    Query 2 3
    Replace 1 3
    Query 1 1

    Sample Output

    4
    7
  • 相关阅读:
    PLSQL配置介绍
    jquery实现无外边框table
    以太坊白皮书
    区块链技术教程,如何从零开始学习以太坊及区块链
    Python机器学习中文版
    史上最全TensorFlow学习资源汇总
    什么是人工智能?终于说明白了
    Python 语音识别
    Step by Step 真正从零开始,TensorFlow详细安装入门图文教程!帮你完成那个最难的从0到1
    什么是加密经济学? 初学者终极指南
  • 原文地址:https://www.cnblogs.com/wang9897/p/10362929.html
Copyright © 2011-2022 走看看