zoukankan      html  css  js  c++  java
  • CF-877E-线段树+哈希

    http://codeforces.com/problemset/problem/877/E

        给出一颗有根树,没个节点上有一个值0/1,有两种操作,一个是选中一个节点,对他所对应的那个子树上所有节点的值进行翻转0->1,1->0,

    第二种操作是询问一个节点对应的子树中所有节点的值的和。

       如果是对一个区间进行上述操作,那么显然就是裸的线段树了,把这颗树按照先序遍历进行重新编号,这样的优点在于,每个节点对应的子树的节点的编号都是从根开始连续增长的,我们只要知道根的编号和树的大小,就能把上述询问转化为了区间修改查询的线段树了!

      思路很棒,可惜自己没想到。

      

     1 #include<iostream>
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 #define LL long long
     5 #define mid ((L+R)>>1)
     6 #define lc (id<<1)
     7 #define rc (id<<1|1)
     8 const int maxn=200010;
     9 vector<int>g[maxn];
    10 int p[maxn],son[maxn];
    11 void dfs(int u,int fa,int &x){
    12     p[u]=x;
    13     son[p[u]]=1;
    14     for(int i=0;i<g[u].size();++i){
    15         if(g[u][i]==fa)continue;
    16         dfs(g[u][i],u,++x);
    17         son[p[u]]+=son[p[g[u][i]]];
    18     }
    19 }
    20 int t[maxn],sum[maxn<<2];
    21 bool tag[maxn<<2];
    22 void build(int id,int L,int R){
    23     //puts("FFF");
    24     if(L==R){
    25         sum[id]=t[L];
    26         return;
    27     }
    28     build(lc,L,mid);
    29     build(rc,mid+1,R);
    30     sum[id]=sum[lc]+sum[rc];
    31 }
    32 void pushdown(int id,int L,int R){
    33     if(tag[id]){
    34         tag[lc]^=1;sum[lc]=(mid-L+1-sum[lc]);
    35         tag[rc]^=1;sum[rc]=(R-mid-sum[rc]);
    36         tag[id]=0;
    37     }
    38 }
    39 int ask(int id,int L,int R,int l,int r){
    40     if(L>=l&&R<=r){
    41         return sum[id];
    42     }
    43     pushdown(id,L,R);
    44     if(r<=mid)return ask(lc,L,mid,l,r);
    45     else if(l>mid) return ask(rc,mid+1,R,l,r);
    46     else return ask(lc,L,mid,l,r)+ask(rc,mid+1,R,l,r);
    47 }
    48 void change(int id,int L,int R,int l,int r){
    49     if(L>=l&&R<=r){
    50         tag[id]^=1;
    51         sum[id]=(R-L+1-sum[id]);
    52         return;
    53     }
    54     pushdown(id,L,R);
    55     if(l<=mid) change(lc,L,mid,l,r);
    56     if(r>mid) change(rc,mid+1,R,l,r);
    57     sum[id]=sum[lc]+sum[rc];
    58 }
    59 int main(){
    60     int n,m,v,x=1;
    61     scanf("%d",&n);
    62     for(int i=2;i<=n;++i){
    63         scanf("%d",&v);
    64         g[v].push_back(i);
    65         g[i].push_back(v);
    66     }
    67     dfs(1,0,x);
    68     for(int i=1;i<=n;++i){
    69         scanf("%d",&t[p[i]]);
    70     }
    71     build(1,1,n);
    72     scanf("%d",&m);
    73     char s[5];
    74     while(m--){
    75         scanf("%s %d",s,&v);
    76         if(s[0]=='g'){
    77             printf("%d
    ",ask(1,1,n,p[v],p[v]+son[p[v]]-1));
    78         }
    79         else{
    80             change(1,1,n,p[v],p[v]+son[p[v]]-1);
    81         }
    82     }
    83     return 0;
    84 }
  • 相关阅读:
    学习官方示例 System.Assigned
    用 TBytesStream 类实现的读文件为十六进制字符的函数
    学习官方示例 System.Hi、System.Lo
    给 TComboBox 添加图标 回复 "heyongan" 的问题
    [每周特惠]WPF编程(第二版) + 设计模式—基于C#的工程化实现及扩展
    【公告】8月28日(周六)早上5:007:00服务器升级
    【网站公告】新Web服务器上线
    欢迎参加上海张江浦东软件园以及分园的技能培训课程
    上周热点回顾(8.309.5)
    上周热点回顾(8.168.22)
  • 原文地址:https://www.cnblogs.com/zzqc/p/9906188.html
Copyright © 2011-2022 走看看