zoukankan      html  css  js  c++  java
  • [SDOI2009]HH的项链-树状数组/线段树

    树状数组:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1000010;
     4 int id[maxn],tree[maxn],vis[maxn],num[maxn];
     5 int n,m;
     6 struct Tree{
     7     int l,r;
     8     int pos;
     9 };
    10 Tree a[maxn];
    11 int buf[17];
    12 inline void read(int &x){
    13     char ch=getchar(); x=0;
    14     while(ch<'0') ch=getchar();
    15     while(ch>='0' && ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    16 }
    17 inline void write(int x){
    18     if(!x){putchar('0');putchar(' ');return;}
    19     register int cnt=0;
    20     while(x)buf[++cnt]=(x%10)+48,x/=10;
    21     while(cnt)putchar(buf[cnt--]);
    22     putchar('
    ');
    23 }
    24 bool cmp(Tree x,Tree y){
    25     return x.r < y.r;
    26 }
    27 int lowbit(int x){
    28     return x & -x;
    29 }
    30 void add(int x,int now){
    31     while(x <= n){
    32         tree[x] += now;
    33         x += lowbit(x);
    34     }
    35 }
    36 int sum(int n){
    37     int ans = 0;
    38     while(n != 0){
    39         ans += tree[n];
    40         n -= lowbit(n);
    41     }
    42     return ans;
    43 }
    44 int main(){
    45     read(n);
    46     for(int i = 1;i <= n;i++)
    47         read(id[i]);
    48     read(m);
    49     for(int i = 1;i <= m;i++){
    50         read(a[i].l);
    51         read(a[i].r);
    52         a[i].pos = i;
    53     }
    54     sort(a+1,a+1+m,cmp);
    55     int next = 1;
    56     for(int i = 1;i <= m;i++){
    57         for(int j = next;j <= a[i].r;j++){
    58             if(vis[id[j]])
    59                 add(vis[id[j]],-1);
    60             add(j,1);
    61             vis[id[j]] = j;
    62         }
    63         next = a[i].r+1;
    64         num[a[i].pos] = sum(a[i].r)-sum(a[i].l-1);
    65     }
    66     for(int i = 1;i <= m;i++)
    67         write(num[i]);
    68     return  0;
    69 }

    线段树:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 5e6+5;
     4 struct segment_tree{
     5     int l,r,s,sum;
     6 };
     7 segment_tree ask[maxn<<2],tree[maxn<<2];
     8 int next[maxn],pre[maxn],a[maxn],x[maxn],n,m;
     9 int buf[17];
    10 inline void read(int &x){
    11     char ch=getchar(); x=0;
    12     while(ch<'0') ch=getchar();
    13     while(ch>='0' && ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    14 }
    15 inline void write(int x){
    16     if(!x){putchar('0');putchar(' ');return;}
    17     register int cnt=0;
    18     while(x)buf[++cnt]=(x%10)+48,x/=10;
    19     while(cnt)putchar(buf[cnt--]);
    20     putchar('
    ');
    21 }
    22 bool cmp1(segment_tree x,segment_tree y){
    23     if (x.l == y.l)return x.r < y.r;
    24     else return x.l < y.l;
    25 }
    26 bool cmp2(segment_tree x,segment_tree y){
    27     return x.s < y.s;
    28 }
    29 inline void pushup(int root){
    30     tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
    31 }
    32 inline void build(int root,int l,int r){
    33     tree[root].l = l;
    34     tree[root].r = r;
    35     if(l == r){
    36         tree[root].sum = a[l];
    37         return;
    38     }
    39     int mid = (l+r)>>1;
    40     build(root<<1,l,mid);
    41     build(root<<1|1,mid+1,r);
    42     pushup(root);
    43 }
    44 inline void update(int root,int k){
    45     if (tree[root].l == k && tree[root].r == k){
    46         a[k] = 1;
    47         tree[root].sum = a[k];
    48         return;
    49     }
    50     int mid = (tree[root].l+tree[root].r)>>1;
    51     if(k <= mid)update(root<<1,k);
    52     else update(root<<1|1,k);
    53     pushup(root);
    54 }
    55 inline int query(int root,int l,int r){
    56     if(tree[root].l == l && tree[root].r == r)
    57         return tree[root].sum;
    58     int mid = (tree[root].l+tree[root].r)>>1;
    59     if(r <= mid)return query(root<<1,l,r);
    60     else 
    61         if(l > mid)return query(root<<1|1,l,r);
    62         else return(query(root<<1,l,mid)+query(root<<1|1,mid+1,r));
    63 }
    64 int main(){
    65     read(n);
    66     for(register int i = 1;i <= n;i++){
    67         read(x[i]);
    68         next[pre[x[i]]] = i;
    69         if(!pre[x[i]])a[i] = 1;
    70         pre[x[i]] = i;
    71     }
    72     build(1,1,n);
    73     scanf("%d",&m);
    74     for(register int i = 1;i <= m;i++){
    75         read(ask[i].l);
    76         read(ask[i].r);
    77         ask[i].s = i;
    78     }
    79     sort(ask+1,ask+m+1,cmp1);
    80     ask[0].l = 1;
    81     for(register int i = 1;i <= m;i++){
    82         if(ask[i-1].l != ask[i].l)
    83             for(register int j = ask[i-1].l;j <= ask[i].l-1;j++)
    84                 if(next[j])update(1,next[j]);
    85         ask[i].sum = query(1,ask[i].l,ask[i].r);
    86     }
    87     sort(ask+1,ask+m+1,cmp2);
    88     for(register int i=1;i<=m;i++)
    89         write(ask[i].sum);
    90     return 0;
    91 }

    别问我为什么补贴出来分块做法...

    因为没学懂!!!没打出来!!!好不容易打出来,给我超时!!!气死了!!!

  • 相关阅读:
    ARC071 简要题解
    ARC070 简要题解
    ARC069 简要题解
    ARC068 简要题解
    ARC067 简要题解
    ARC066 简要题解
    ARC065 简要题解
    长链剖分优化dp三例题
    CF815D Karen and Cards 官方题解翻译
    [九省联考2018] IIIDX 线段树+贪心
  • 原文地址:https://www.cnblogs.com/wangyifan124/p/10320268.html
Copyright © 2011-2022 走看看