[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 }

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

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

原文地址:https://www.cnblogs.com/wangyifan124/p/10320268.html