zoukankan      html  css  js  c++  java
  • hdu 5039 线段树+dfs序

    http://acm.hdu.edu.cn/showproblem.php?pid=5039

    给定一棵树,边权为0/1。m个操作支持翻转一条边的权值或者询问树上有多少条路径的边权和为奇数。

    用树形dfs出每个点到根的路径上边权和是否为奇数;

    由于翻转一个边只会连带影响其下的子节点,所有线段树记录更新区间,odd记录到根的路径上边权和为奇数的个数,每次只需更新和查询odd,没有lazy会超时


    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <map>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define RD(x) scanf("%d",&x)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define clr0(x) memset(x,0,sizeof(x))
    typedef long long LL;
    #define L(x) (x<<1)
    #define R(x) ((x<<1)|1)
    #define MI(x,y) ((x+y)>>1)
    const int maxn = 30010;
    int head[maxn],l[maxn],r[maxn],val[maxn];
    int n,m,tot,idx;
    struct edge{
        int u,v,f,next;
    }ed[maxn<<1];
    map<string , int> hash;
    struct tree{
        int l,r,odd,//  odd为到根的路径上边权和为奇数的个数
        lazy;// lazy控制翻转次数,翻转偶数次相当于没有翻转
    }d[maxn<<2];
    void add(int u,int v,int f)
    {
        ed[tot] = (edge){u,v,f,head[u]},head[u] = tot++;
        ed[tot] = (edge){v,u,f,head[v]},head[v] = tot++;
    }
    void dfs(int u,int f,int fa)
    {
        idx++;
        val[idx] = f;
        l[u] = idx;
        for(int i = head[u];i != -1;i = ed[i].next){
            if(ed[i].v != fa){
                dfs(ed[i].v,f ^ ed[i].f,u);
            }
        }
        r[u] = idx;
    }
    void up(int root)
    {
        d[root].odd = d[L(root)].odd + d[R(root)].odd;
    }
    void build(int l,int r,int root)
    {
        d[root] = (tree){l,r,val[l],0};
        if(l == r)
            return ;
        int mid = MI(l,r);
        build(l,mid,L(root));
        build(mid+1,r,R(root));
        up(root);
    }
    void down(int root) {
    	if (d[root].lazy) {
    		d[L(root)].lazy ^= 1;// 翻转偶数次相当于没翻转,所以不需要更新其子节点
    		d[R(root)].lazy ^= 1;
    		d[L(root)].odd = d[L(root)].r - d[L(root)].l + 1 - d[L(root)].odd;
    		d[R(root)].odd = d[R(root)].r - d[R(root)].l + 1 - d[R(root)].odd;
    		d[root].lazy = 0;
    	}
    }
    void update(int l, int r, int root)
    {
    	if (d[root].l == l && d[root].r == r) {
    		d[root].odd = d[root].r - d[root].l + 1 - d[root].odd;
    		d[root].lazy ^= 1;
    		return;
    	}
    	down(root);
    	int mid = MI(d[root].l,d[root].r);
    	if (r <= mid)
    		update(l, r, L(root));
    	else if (l > mid)
    		update(l, r, R(root));
    	else {
    		update(l, mid, L(root));
    		update(mid + 1, r, R(root));
    	}
    	up(root);
    }
    
    int main()
    {
        int _;
        RD(_);
        string str,rts;
        char q[2];
        for(int cas = 1;cas <= _;++cas){
            printf("Case #%d:
    ", cas);
            hash.clear();
            RD(n);
            for(int i = 1;i <= n;++i){
                cin>>str;
                hash[str] = i;
                head[i] = -1;
            }
            tot = 0;
            int u,v,f;
            for(int i = 1;i < n;++i){
                cin>>str>>rts;
                RD(f);
                add(hash[str],hash[rts],f);
            }
            idx = 0;
            dfs(1,0,0);
            build(1,n,1);
            RD(m);
            while(m--){
                scanf("%s",q);
                if(q[0] == 'Q'){
                    printf("%d
    ",d[1].odd * (n - d[1].odd) * 2);
                }else{
                    RD(f);
                    f = (f-1)<<1;// 边的记录用例两单位的ed
                    u = ed[f].u,v = ed[f].v;
                    if(l[u] > l[v])
                        update(l[u],r[u],1);
                    else
                        update(l[v],r[v],1);
                }
            }
        }
    	return 0;
    }
    


  • 相关阅读:
    状态模式
    适配器模式
    观察者模式
    浮点数在内存中的存储方式
    建造者模式
    外观模式
    模版方法模式
    原型模式
    Python 学习笔记6 变量-元组
    Python 学习笔记5 变量-列表
  • 原文地址:https://www.cnblogs.com/zibaohun/p/4046846.html
Copyright © 2011-2022 走看看