zoukankan      html  css  js  c++  java
  • 专题训练之主席树

    推荐几个博客:http://www.cnblogs.com/zyf0163/p/4749042.html 树状结构之主席树

    https://blog.csdn.net/creatorx/article/details/75446472 最详细的讲解,让你一次学会主席树

    https://blog.csdn.net/jerans/article/details/75807666 主席树题集

    https://blog.csdn.net/HTT_H/article/details/47704209 主席树入门专题

    https://www.cnblogs.com/RabbitHu/p/segtree.html  递归版主席树

    递归版模板大体结构:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn=5e4+10;
     7 const int maxm=2e6+10;
     8 int tot;
     9 int c[maxm],lson[maxm],rson[maxm];
    10 int T[maxn];
    11 
    12 void build(int &root,int l,int r)
    13 {
    14     root=++tot;
    15     if ( l==r ) return;
    16     int mid=(l+r)/2;
    17     build(lson[root],l,mid);
    18     build(rson[root],mid+1,r);
    19 }
    20 
    21 void update(int root,int &rt,int p,int val,int l,int r)
    22 {
    23     rt=++tot;
    24     lson[rt]=lson[root],rson[rt]=rson[root];
    25     c[rt]=c[root]+val;
    26     if ( l==r ) return;
    27     int mid=(l+r)/2;
    28     if ( p<=mid ) update(lson[rt],lson[rt],p,val,l,mid);
    29     else update(rson[rt],rson[rt],p,val,mid+1,r);
    30 }
    31 
    32 int query(int rt,int L,int R,int l,int r)
    33 {
    34     if ( L<=l && r<=R ) return c[rt];
    35     int mid=(l+r)/2;
    36     int ans=0;
    37     if ( L<=mid ) ans+=query(lson[rt],L,R,l,mid);
    38     if ( R>mid ) ans+=query(rson[rt],L,R,mid+1,r);
    39     return ans;
    40 }
    主席树(递归版)

    1.(HDOJ2665)http://acm.hdu.edu.cn/showproblem.php?pid=2665

    (POJ2104)http://poj.org/problem?id=2104

    (POJ2761)http://poj.org/problem?id=2761

    题意:求区间第K大,主席树模板题

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 using namespace std;
      6 const int maxn=1e5+10;
      7 const int maxm=3e6+10;
      8 int n,q,m,tot;
      9 int a[maxn],t[maxn];
     10 int T[maxn],lson[maxm],rson[maxm],c[maxm];
     11 
     12 void init_hash()
     13 {
     14     for ( int i=1;i<=n;i++ ) t[i]=a[i];
     15     sort(t+1,t+1+n);
     16     m=unique(t+1,t+1+n)-(t+1);
     17 }
     18 
     19 int build(int l,int r)
     20 {
     21     int root=tot++;
     22     c[root]=0;
     23     if ( l!=r )
     24     {
     25         int mid=(l+r)/2;
     26         lson[root]=build(l,mid);
     27         rson[root]=build(mid+1,r);
     28     }
     29     return root;
     30 }
     31 
     32 int hash_(int x)
     33 {
     34     return lower_bound(t+1,t+1+m,x)-t;
     35 }
     36 
     37 int update(int root,int pos,int val)
     38 {
     39     int rt=tot++,tmp=rt;
     40     c[rt]=c[root]+val;
     41     int l=1,r=m;
     42     while ( l<r )
     43     {
     44         int mid=(l+r)/2;
     45         if ( pos<=mid )
     46         {
     47             lson[rt]=tot++;rson[rt]=rson[root];
     48             rt=lson[rt];root=lson[root];
     49             r=mid;
     50         }
     51         else 
     52         {
     53             rson[rt]=tot++;lson[rt]=lson[root];
     54             rt=rson[rt];root=rson[root];
     55             l=mid+1;
     56         }
     57         c[rt]=c[root]+val;
     58     }
     59     return tmp;
     60 }
     61 
     62 int query(int lrt,int rrt,int k)
     63 {
     64     int l=1,r=m;
     65     while ( l<r )
     66     {
     67         int mid=(l+r)/2;
     68         if ( c[lson[rrt]]-c[lson[lrt]]>=k )
     69         {
     70             r=mid;
     71             lrt=lson[lrt];
     72             rrt=lson[rrt];
     73         }
     74         else 
     75         {
     76             l=mid+1;
     77             k-=c[lson[rrt]]-c[lson[lrt]];
     78             lrt=rson[lrt];
     79             rrt=rson[rrt];
     80         }
     81     }
     82     return l;
     83 }
     84 
     85 int main()
     86 {
     87     int Case;
     88     scanf("%d",&Case);
     89     while ( Case-- )
     90     {
     91         scanf("%d%d",&n,&q);
     92         tot=0;
     93         for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]);
     94         init_hash();
     95         T[0]=build(1,m);
     96         for ( int i=1;i<=n;i++ )
     97         {
     98             int pos=hash_(a[i]);
     99             T[i]=update(T[i-1],pos,1);
    100         }
    101         while ( q-- )
    102         {
    103             int l,r,k;
    104             scanf("%d%d%d",&l,&r,&k);
    105             printf("%d
    ",t[query(T[l-1],T[r],k)]);
    106         }
    107     }
    108     return 0;
    109 }
    HDOJ2665
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn=1e5+10;
     7 const int maxm=3e6+10;
     8 int tot,n,q,m;
     9 int a[maxn],t[maxn];
    10 int c[maxm],lson[maxm],rson[maxm];
    11 int T[maxn];
    12 
    13 void init_hash()
    14 {
    15     for ( int i=1;i<=n;i++ ) t[i]=a[i];
    16     sort(t+1,t+1+n);
    17     m=unique(t+1,t+1+n)-(t+1);
    18 }
    19 
    20 int hash_(int x)
    21 {
    22     return lower_bound(t+1,t+1+m,x)-t;
    23 }
    24 
    25 void build(int &root,int l,int r)
    26 {
    27     root=++tot;
    28     if ( l==r ) return;
    29     int mid=(l+r)/2;
    30     build(lson[root],l,mid);
    31     build(rson[root],mid+1,r);
    32 }
    33 
    34 void update(int root,int &rt,int p,int val,int l,int r)
    35 {
    36     rt=++tot;
    37     lson[rt]=lson[root],rson[rt]=rson[root];
    38     c[rt]=c[root]+val;
    39     if ( l==r ) return;
    40     int mid=(l+r)/2;
    41     if ( p<=mid ) update(lson[rt],lson[rt],p,val,l,mid);
    42     else update(rson[rt],rson[rt],p,val,mid+1,r);
    43 }
    44 
    45 int query(int rt_,int rt,int l,int r,int k)
    46 {
    47     if ( l==r ) return l;
    48     int mid=(l+r)/2;
    49     int sum=c[lson[rt_]]-c[lson[rt]];
    50     if ( sum>=k ) return query(lson[rt_],lson[rt],l,mid,k);
    51     else return query(rson[rt_],rson[rt],mid+1,r,k-sum);
    52 }
    53 
    54 int main()
    55 {
    56     int Case;
    57     scanf("%d",&Case);
    58     while ( Case-- )
    59     {
    60         scanf("%d%d",&n,&q);
    61         tot=0;
    62         for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]);
    63         init_hash();
    64         build(T[0],1,m);
    65         for ( int i=1;i<=n;i++ )
    66         {
    67             int pos=hash_(a[i]);
    68             update(T[i-1],T[i],pos,1,1,m);
    69         }
    70         while ( q-- )
    71         {
    72             int l,r,k;
    73             scanf("%d%d%d",&l,&r,&k);
    74             printf("%d
    ",t[query(T[r],T[l-1],1,m,k)]);
    75         }
    76     }
    77     return 0;
    78 }
    HDOJ2665(递归版)

    2.(HDOJ4417)http://acm.hdu.edu.cn/showproblem.php?pid=4417

    题意:求给定区间<=k的数有多少

    分析:在模板上将query部分修改一下即可,对于区间[L,R]来说,只需要将第R颗线段树上的[0,k]区间内的值减去第L-1颗线段树上对应区间即可。离线在线都行,离线做法需要将每次访问的k也添加进入hash数组,而对于在线来说转化后的数转化前相对于给定的k来说只能变小不能变大即可

    注意:题目给的区间范围从0开始,要将其转化成从1开始

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 using namespace std;
      6 const int maxn=1e5+10;
      7 const int maxm=3e6+10;
      8 int n,q,m,tot;
      9 int a[maxn],t[maxn];
     10 int T[maxn],lson[maxm],rson[maxm],c[maxm];
     11 
     12 void init_hash()
     13 {
     14     for ( int i=1;i<=n;i++ ) t[i]=a[i];
     15     sort(t+1,t+1+n);
     16     m=unique(t+1,t+1+n)-(t+1);
     17 }
     18 
     19 int build(int l,int r)
     20 {
     21     int root=tot++;
     22     c[root]=0;
     23     if ( l!=r )
     24     {
     25         int mid=(l+r)/2;
     26         lson[root]=build(l,mid);
     27         rson[root]=build(mid+1,r);
     28     }
     29     return root;
     30 }
     31 
     32 int hash_(int x)
     33 {
     34     return lower_bound(t+1,t+1+m,x)-t;
     35 }
     36 
     37 int update(int root,int pos,int val)
     38 {
     39     int rt=tot++,tmp=rt;
     40     c[rt]=c[root]+val;
     41     int l=1,r=m;
     42     while ( l<r )
     43     {
     44         int mid=(l+r)/2;
     45         if ( pos<=mid )
     46         {
     47             lson[rt]=tot++;rson[rt]=rson[root];
     48             rt=lson[rt];root=lson[root];
     49             r=mid;
     50         }
     51         else 
     52         {
     53             rson[rt]=tot++;lson[rt]=lson[root];
     54             rt=rson[rt];root=rson[root];
     55             l=mid+1;
     56         }
     57         c[rt]=c[root]+val;
     58     }
     59     return tmp;
     60 }
     61 
     62 int query(int lrt,int rrt,int k)
     63 {
     64     int ret=0;
     65     int l=1,r=m;
     66     while ( l<r )
     67     {
     68         int mid=(l+r)/2;
     69         if ( k<=mid )
     70         {
     71             r=mid;
     72             lrt=lson[lrt];
     73             rrt=lson[rrt];
     74         }
     75         else 
     76         {
     77             ret+=c[lson[rrt]]-c[lson[lrt]];
     78             l=mid+1;
     79             lrt=rson[lrt];
     80             rrt=rson[rrt];
     81         }
     82     }
     83     ret+=c[rrt]-c[lrt];
     84     return ret;
     85 }
     86 
     87 int main()
     88 {
     89     int Case,h;
     90     scanf("%d",&Case);
     91     for ( h=1;h<=Case;h++ )
     92     {
     93         scanf("%d%d",&n,&q);
     94         tot=0;
     95         for ( int i=1;i<=n;i++ ) 
     96         {
     97             scanf("%d",&a[i]);
     98             a[i]++;
     99         }
    100         init_hash();
    101         T[0]=build(1,m);
    102         for ( int i=1;i<=n;i++ )
    103         {
    104             int pos=hash_(a[i]);
    105             T[i]=update(T[i-1],pos,1);
    106         }
    107         printf("Case %d:
    ",h);
    108         while ( q-- )
    109         {
    110             int l,r,k,p;
    111             scanf("%d%d%d",&l,&r,&k);
    112             l++,r++,k++;
    113             p=hash_(k);
    114             if ( t[p]>k ) p--;
    115             if ( p==0 ) printf("0
    ");
    116             else printf("%d
    ",query(T[l-1],T[r],p));
    117         }
    118     }
    119     return 0;
    120 }
    HDOJ4417(在线)
      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 using namespace std;
      6 const int maxn=1e5+10;
      7 const int maxm=3e6+10;
      8 int n,q,m,tot;
      9 int a[maxn],t[maxn*2],l[maxn],r[maxn],val[maxn];
     10 int T[maxn],lson[maxm],rson[maxm],c[maxm];
     11 
     12 void init_hash()
     13 {
     14     for ( int i=1;i<=n;i++ ) t[i]=a[i];
     15     for ( int i=1;i<=q;i++ ) t[i+n]=val[i];
     16     sort(t+1,t+1+n+q);
     17     m=unique(t+1,t+1+n+q)-(t+1);
     18 }
     19 
     20 int build(int l,int r)
     21 {
     22     int root=tot++;
     23     c[root]=0;
     24     if ( l!=r )
     25     {
     26         int mid=(l+r)/2;
     27         lson[root]=build(l,mid);
     28         rson[root]=build(mid+1,r);
     29     }
     30     return root;
     31 }
     32 
     33 int hash_(int x)
     34 {
     35     return lower_bound(t+1,t+1+m,x)-t;
     36 }
     37 
     38 int update(int root,int pos,int val)
     39 {
     40     int rt=tot++,tmp=rt;
     41     c[rt]=c[root]+val;
     42     int l=1,r=m;
     43     while ( l<r )
     44     {
     45         int mid=(l+r)/2;
     46         if ( pos<=mid )
     47         {
     48             lson[rt]=tot++;rson[rt]=rson[root];
     49             rt=lson[rt];root=lson[root];
     50             r=mid;
     51         }
     52         else 
     53         {
     54             rson[rt]=tot++;lson[rt]=lson[root];
     55             rt=rson[rt];root=rson[root];
     56             l=mid+1;
     57         }
     58         c[rt]=c[root]+val;
     59     }
     60     return tmp;
     61 }
     62 
     63 int query(int lrt,int rrt,int k)
     64 {
     65     int ret=0;
     66     int l=1,r=m;
     67     while ( l<r )
     68     {
     69         int mid=(l+r)/2;
     70         if ( k<=mid )
     71         {
     72             r=mid;
     73             lrt=lson[lrt];
     74             rrt=lson[rrt];
     75         }
     76         else 
     77         {
     78             ret+=c[lson[rrt]]-c[lson[lrt]];
     79             l=mid+1;
     80             lrt=rson[lrt];
     81             rrt=rson[rrt];
     82         }
     83     }
     84     ret+=c[rrt]-c[lrt];
     85     return ret;
     86 }
     87 
     88 int main()
     89 {
     90     int Case,h;
     91     scanf("%d",&Case);
     92     for ( h=1;h<=Case;h++ )
     93     {
     94         scanf("%d%d",&n,&q);
     95         tot=0;
     96         for ( int i=1;i<=n;i++ ) 
     97         {
     98             scanf("%d",&a[i]);
     99             a[i]++;
    100         }
    101         for ( int i=1;i<=q;i++ ) {
    102             scanf("%d%d%d",&l[i],&r[i],&val[i]);
    103             l[i]++,r[i]++,val[i]++;
    104         }
    105         init_hash();
    106         T[0]=build(1,m);
    107         for ( int i=1;i<=n;i++ )
    108         {
    109             int pos=hash_(a[i]);
    110             T[i]=update(T[i-1],pos,1);
    111         }
    112         printf("Case %d:
    ",h);
    113         for ( int i=1;i<=q;i++ )
    114         {
    115             int L,R,k;
    116             L=l[i],R=r[i],k=val[i];
    117             k=hash_(k);
    118             printf("%d
    ",query(T[L-1],T[R],k));
    119         }
    120     }
    121     return 0;
    122 }
    HDOJ4417(离线)

    3.(SPOJ3267)http://www.spoj.com/problems/DQUERY/

    题意:给出一个长度为n 的数列,有q 个询问,每个询问给出数对 [i,j],需要你给出这一段中有多少不同的数字

    分析:利用map记录每个数的位置,主席树建新树的时候,如果当前元素出现过,那么把这个元素上次出现的位置减一,然后当前位置加一,如果没出现过就是普通的建树操作。

    对于查询[l, r]我们只需要取出第r棵树,然后输出这棵树[l,r]之间的和,因为是按从1到n的顺序插入的,所以每次只需要求>=l的个数即可。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<map>
      6 using namespace std;
      7 const int maxn=3e4+10;
      8 const int maxm=3e6+10;
      9 int n,q,tot;
     10 int a[maxn];
     11 int T[maxn],lson[maxm],rson[maxm],c[maxm];
     12 
     13 int build(int l,int r)
     14 {
     15     int root=tot++;
     16     c[root]=0;
     17     if ( l!=r )
     18     {
     19         int mid=(l+r)/2;
     20         lson[root]=build(l,mid);
     21         rson[root]=build(mid+1,r);
     22     }
     23     return root;
     24 }
     25 
     26 int update(int root,int pos,int val)
     27 {
     28     int rt=tot++,tmp=rt;
     29     c[rt]=c[root]+val;
     30     int l=1,r=n;
     31     while ( l<r )
     32     {
     33         int mid=(l+r)/2;
     34         if ( pos<=mid )
     35         {
     36             lson[rt]=tot++;rson[rt]=rson[root];
     37             rt=lson[rt];root=lson[root];
     38             r=mid;
     39         }
     40         else 
     41         {
     42             rson[rt]=tot++;lson[rt]=lson[root];
     43             rt=rson[rt];root=rson[root];
     44             l=mid+1;
     45         }
     46         c[rt]=c[root]+val;
     47     }
     48     return tmp;
     49 }
     50 
     51 int query(int rt,int lpos)
     52 {
     53     int ret=0;
     54     int l=1,r=n;
     55     while ( lpos>l )
     56     {
     57         int mid=(l+r)/2;
     58         if ( lpos<=mid )
     59         {
     60             r=mid;
     61             ret+=c[rson[rt]];
     62             rt=lson[rt];
     63         }
     64         else 
     65         {
     66             rt=rson[rt];
     67             l=mid+1;
     68         }
     69     }
     70     return ret+c[rt];
     71 }
     72 
     73 int main()
     74 {
     75     int Case;
     76     while ( scanf("%d",&n)!=EOF )
     77     {
     78         tot=0;
     79         for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]);
     80         T[0]=build(1,n);
     81         map<int,int>mp;
     82         for ( int i=1;i<=n;i++ )
     83         {
     84             if ( mp.find(a[i])!=mp.end() ) 
     85             {
     86                 int tmp=update(T[i-1],mp[a[i]],-1);
     87                 T[i]=update(tmp,i,1);
     88             }
     89             else T[i]=update(T[i-1],i,1);
     90             mp[a[i]]=i;
     91         }
     92         scanf("%d",&q);
     93         while ( q-- )
     94         {
     95             int l,r;
     96             scanf("%d%d",&l,&r);
     97             printf("%d
    ",query(T[r],l));
     98         }
     99     }
    100     return 0;
    101 }
    SPOJ3267

    4.(ZOJ2112)http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112

    题意:给定一串序列,有两种操作,一种是求区间[l,r]第k大,另外一种是将a[i]=t

    带修改的主席树,推荐几个博客:http://www.cnblogs.com/Empress/p/4659824.html

    https://blog.csdn.net/acm_cxlove/article/details/8565309

    http://www.cnblogs.com/Rlemon/archive/2013/05/24/3096264.html

    模板来自kuangbin:http://www.cnblogs.com/kuangbin/p/3308118.html

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 using namespace std;
      6 const int maxn=60010;
      7 const int maxm=2500010;
      8 int n,q,m,tot;
      9 int a[maxn],t[maxn];
     10 int T[maxn],lson[maxm],rson[maxm],c[maxm];
     11 int S[maxn];
     12 struct Query{
     13     int kind;
     14     int l,r,k;
     15 }query[10010];
     16 
     17 void init_hash(int k)
     18 {
     19     sort(t+1,t+k+1);
     20     m=unique(t+1,t+k+1)-(t+1);
     21 }
     22 
     23 int hash_(int x)
     24 {
     25     return lower_bound(t+1,t+m+1,x)-t;
     26 }
     27 
     28 int build(int l,int r)
     29 {
     30     int root=tot++;
     31     c[root]=0;
     32     if ( l!=r )
     33     {
     34         int mid=(l+r)/2;
     35         lson[root]=build(l,mid);
     36         rson[root]=build(mid+1,r);
     37     }
     38     return root;
     39 }
     40 
     41 int update(int root,int pos,int val)
     42 {
     43     int rt=tot++,tmp=rt;
     44     c[rt]=c[root]+val;
     45     int l=1,r=m;
     46     while ( l<r )
     47     {
     48         int mid=(l+r)/2;
     49         if ( pos<=mid )
     50         {
     51             lson[rt]=tot++;rson[rt]=rson[root];
     52             rt=lson[rt];root=lson[root];
     53             r=mid;
     54         }
     55         else 
     56         {
     57             rson[rt]=tot++;lson[rt]=lson[root];
     58             rt=rson[rt];root=rson[root];
     59             l=mid+1;
     60         }
     61         c[rt]=c[root]+val;
     62     }
     63     return tmp;
     64 }
     65 
     66 int lowbit(int x)
     67 {
     68     return x&(-x);
     69 }
     70 
     71 int used[maxn];
     72 void add(int x,int pos,int val)
     73 {
     74     while ( x<=n )
     75     {
     76         S[x]=update(S[x],pos,val);
     77         x+=lowbit(x);
     78     }
     79 }
     80 
     81 int sum(int x)
     82 {
     83     int ret=0;
     84     while ( x>0 )
     85     {
     86         ret+=c[lson[used[x]]];
     87         x-=lowbit(x);
     88     }
     89     return ret;
     90 }
     91 
     92 int Q(int left,int right,int k)
     93 {
     94     int lrt=T[left];
     95     int rrt=T[right];
     96     int l=1,r=m;
     97     for ( int i=left;i>0;i-=lowbit(i)) used[i]=S[i];
     98     for ( int i=right;i>0;i-=lowbit(i)) used[i]=S[i];
     99     while ( l<r )
    100     {
    101         int mid=(l+r)/2;
    102         int tmp=sum(right)-sum(left)+c[lson[rrt]]-c[lson[lrt]];
    103         if ( tmp>=k )
    104         {
    105             r=mid;
    106             for ( int i=left;i>0;i-=lowbit(i)) used[i]=lson[used[i]];
    107             for ( int i=right;i>0;i-=lowbit(i)) used[i]=lson[used[i]];
    108             lrt=lson[lrt];
    109             rrt=lson[rrt];
    110         }
    111         else 
    112         {
    113             l=mid+1;
    114             k-=tmp;
    115             for ( int i=left;i>0;i-=lowbit(i)) used[i]=rson[used[i]];
    116             for ( int i=right;i>0;i-=lowbit(i)) used[i]=rson[used[i]];
    117             lrt=rson[lrt];
    118             rrt=rson[rrt];
    119         }
    120     }
    121     return l;
    122 }
    123 
    124 int main()
    125 {
    126     int Case;
    127     scanf("%d",&Case);
    128     while ( Case-- )
    129     {
    130         scanf("%d%d",&n,&q);
    131         tot=0;
    132         m=0;
    133         for ( int i=1;i<=n;i++ ) 
    134         {
    135             scanf("%d",&a[i]);
    136             t[++m]=a[i];
    137         }
    138         char op[10];
    139         for ( int i=0;i<q;i++ )
    140         {
    141             scanf("%s",op);
    142             if ( op[0]=='Q' )
    143             {
    144                 query[i].kind=0;
    145                 scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k);
    146             }
    147             else
    148             {
    149                 query[i].kind=1;
    150                 scanf("%d%d",&query[i].l,&query[i].r);
    151                 t[++m]=query[i].r;
    152             }
    153         }
    154         init_hash(m);
    155         T[0]=build(1,m);
    156         for ( int i=1;i<=n;i++ )
    157         {
    158             int pos=hash_(a[i]);
    159             T[i]=update(T[i-1],pos,1);
    160         }
    161         for ( int i=1;i<=n;i++ ) S[i]=T[0];
    162         for ( int i=0;i<q;i++ )
    163         {
    164             if ( query[i].kind==0 ) printf("%d
    ",t[Q(query[i].l-1,query[i].r,query[i].k)]);
    165             else 
    166             {
    167                 add(query[i].l,hash_(a[query[i].l]),-1);
    168                 add(query[i].l,hash_(query[i].r),1);
    169                 a[query[i].l]=query[i].r;
    170             }
    171         }
    172     }
    173     return 0;
    174 }
    ZOJ2112

    5.(HDOJ4348)http://acm.hdu.edu.cn/showproblem.php?pid=4348

    题意:给出一段长度为n的序列,有4种操作。初始时,时间戳=0

    a.C l r d [l,r]区间内的数+d,时间戳++

    b.Q l r 求当前时间戳下[l,r]区间的和

    c.H l r t 求时间戳=t下[l,r]区间的和

    d.B t  时间戳=t

    分析:推荐两个讲解较为详细的博客https://blog.csdn.net/glqac/article/details/45103859

    https://blog.csdn.net/kirito16/article/details/47266801

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 using namespace std;
      6 typedef long long ll;
      7 const int maxn=1e5+10;
      8 const int maxm=3e6+10;
      9 int n,q,tot;
     10 int a[maxn];
     11 int T[maxn],lson[maxm],rson[maxm];
     12 ll sum[maxm],add[maxm];
     13 
     14 int build(int l,int r)
     15 {
     16     int root=tot++;
     17     add[root]=0;
     18     if ( l!=r )
     19     {
     20         int mid=(l+r)/2;
     21         lson[root]=build(l,mid);
     22         rson[root]=build(mid+1,r);
     23     }
     24     else
     25     {
     26         scanf("%lld",&sum[root]);
     27         return root;
     28     }
     29     sum[root]=sum[lson[root]]+sum[rson[root]];
     30     return root;
     31 }
     32 
     33 
     34 void pushup(int rt,int len)
     35 {
     36     sum[rt]=sum[lson[rt]]+sum[rson[rt]]+add[lson[rt]]*(len-len/2)+add[rson[rt]]*(len/2);
     37 }
     38 
     39 int A,B;
     40 ll val;
     41 
     42 int update(int root,int l,int r)
     43 {
     44     int rt=tot++;
     45     add[rt]=add[root];
     46     if ( A<=l && r<=B )
     47     {
     48         sum[rt]=sum[root];
     49         add[rt]=add[root]+val;
     50         lson[rt]=lson[root];
     51         rson[rt]=rson[root];
     52         return rt;
     53     }
     54     int mid=(l+r)/2;
     55     if ( A<=mid ) lson[rt]=update(lson[root],l,mid);
     56     else lson[rt]=lson[root];
     57     if ( B>mid ) rson[rt]=update(rson[root],mid+1,r);
     58     else rson[rt]=rson[root];
     59     pushup(rt,r-l+1);
     60     return rt;
     61 }
     62 
     63 ll query(int root,int l,int r,ll add_)
     64 {
     65     if ( A<=l && r<=B ) return sum[root]+(add_+add[root])*(r-l+1);
     66     ll ans=0;
     67     int mid=(l+r)/2;
     68     if ( A<=mid ) ans+=query(lson[root],l,mid,add[root]+add_);
     69     if ( B>mid ) ans+=query(rson[root],mid+1,r,add[root]+add_);
     70     return ans;
     71 }
     72 
     73 int main()
     74 {
     75     char op[5];
     76     int now,Case=0;
     77     while ( scanf("%d%d",&n,&q)!=EOF )
     78     {
     79         if ( Case!=0 ) printf("
    ");
     80         Case++;
     81         tot=0;
     82         T[0]=build(1,n);
     83         now=0;
     84         while ( q-- )
     85         {
     86             ll ans;
     87             int k;
     88             scanf("%s",op);
     89             if ( op[0]=='C' ) 
     90             {
     91                 scanf("%d%d%lld",&A,&B,&val);
     92                 T[now+1]=update(T[now],1,n);
     93                 now++;
     94             }
     95             else if ( op[0]=='Q' )
     96             {
     97                 scanf("%d%d",&A,&B);
     98                 ans=query(T[now],1,n,0); 
     99                 printf("%lld
    ",ans);
    100             }
    101             else if ( op[0]=='H' )
    102             {
    103                 scanf("%d%d%d",&A,&B,&k);
    104                 ans=query(T[k],1,n,0); 
    105                 printf("%lld
    ",ans);
    106             }
    107             else if ( op[0]=='B' ) 
    108             {
    109                 scanf("%d",&k);
    110                 now=k;
    111                 tot=T[now+1];
    112             }
    113         }
    114     }
    115     return 0;
    116 }
    HDOJ4348
  • 相关阅读:
    Android(java)学习笔记68:使用proguard混淆android代码
    SGU 194 Reactor Cooling
    关于流量有上下界的网络流问题的求解
    关于最小割的求解方法
    HDU 5311 Hidden String
    POJ 3548 Restoring the digits
    POJ 2062 HDU 1528 ZOJ 2223 Card Game Cheater
    ZOJ 1967 POJ 2570 Fiber Network
    HDU 1969 Pie
    HDU 1956 POJ 1637 Sightseeing tour
  • 原文地址:https://www.cnblogs.com/HDUjackyan/p/9069311.html
Copyright © 2011-2022 走看看