[SDOI2009]HH的项链-树状数组/线段树
Posted wangyifan124
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 }
别问我为什么补贴出来分块做法...
因为没学懂!!!没打出来!!!好不容易打出来,给我超时!!!气死了!!!
以上是关于[SDOI2009]HH的项链-树状数组/线段树的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj1878] [SDOI2009]HH的项链(树状数组+离线)
BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]