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
  • 相关阅读:
    Hibernate逆向工程
    使用Hibernate连接Oracle 无法识别生成的SQL问题
    法线的变换矩阵
    搭建Struts2开发环境
    留存: struts2+jquery+json集成
    一些WebGL的资源
    9个WebGL的演示
    WPF动画制作简单的按钮动画
    C# /windowForm/WPF/SilverLight里面操作Word帮助类提供给大家
    高斯投影正反算的代码
  • 原文地址:https://www.cnblogs.com/HDUjackyan/p/9069311.html
Copyright © 2011-2022 走看看