一些简单的树状数组题
Posted zhou2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些简单的树状数组题相关的知识,希望对你有一定的参考价值。
题目链接:CF961E
大意:给定一列数$a_i$,求满足下列条件的数对$(x,y)$的数量:$(1)x<y,(2)a_xgeq y,(3)a_ygeq x$
如果只有前两个条件那就是很简单的树状数组题
但是这样做是无法满足第三个条件的
所以我们可以预处理出满足第三个条件的情况,并将它们压进vector中
这样在统计答案时直接将vector中的元素拿出来,在树状数组上求和
注意到在此题中$a_i>n$与$a_i=n$是等价的,所以直接将大于n的$a_i$赋为$n$可以避免离散化
#include<iostream> #include<string> #include<string.h> #include<stdio.h> #include<algorithm> #include<vector> #include<queue> #include<map> using namespace std; int tree[200500],n,a[200500]; vector<int> v[200500]; int lowbit(int x) { return x&(-x); } void add(int pos,int val) { int i; for (i=pos;i<=n;i+=lowbit(i)) tree[i]+=val; } int query(int pos) { int i,ans=0; for (i=pos;i>0;i-=lowbit(i)) ans+=tree[i]; return ans; } int main() { scanf("%d",&n); int i; for (i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]=min(a[i],n); v[min(i-1,a[i])].push_back(i); } long long ans=0; memset(tree,0,sizeof(tree)); for (i=1;i<=n;i++) { add(a[i],1); int j,len=v[i].size(); for (j=0;j<len;j++) ans+=query(n)-query(v[i][j]-1); } printf("%I64d",ans); return 0; }
题目链接:CF827C
大意:给定一个由"A","G","T","C"组成的字符串,有如下两种操作
? $1 x c$ :将位置为x的字符替换成c
? $2 l r e$:给出一个字符串,它的循环节是$e$(即这个字符串为$eeldots$),将它与原字符串的子串$[lldots r]$进行比较,求出有多少位能够匹配
本题的关键在于$eleq 10$,所以很多东西要在$e$上做文章
我们可以对每个字符开$10*10$个树状数组(记做$[i][j]$),表示当$e$的长度为$j$时这个字符能处在$e$的第$i$位
树状数组再开两维记录当前的元素是什么以及在原串中的位置
在查询时,对每一个字符统计它的贡献即可
1 #include<iostream> 2 #include<string> 3 #include<string.h> 4 #include<stdio.h> 5 #include<algorithm> 6 #include<vector> 7 #include<queue> 8 #include<map> 9 using namespace std; 10 const int maxn=1e5+10; 11 int tree[11][11][5][maxn],n,q; 12 char a[100500]; 13 map<char,int>mp; 14 15 int lowbit(int x) 16 { 17 return x&(-x); 18 } 19 20 void add(int x,int y,int id,int pos,int val) 21 { 22 int i; 23 for (i=pos;i<=maxn;i+=lowbit(i)) 24 { 25 tree[x][y][id][i]+=val; 26 } 27 } 28 29 int query(int x,int y,int id,int pos) 30 { 31 int i,ans=0; 32 for (i=pos;i>0;i-=lowbit(i)) 33 ans+=tree[x][y][id][i]; 34 return ans; 35 } 36 37 int main() 38 { 39 scanf("%s",a); 40 memset(tree,0,sizeof(tree)); 41 mp[‘A‘]=0;mp[‘T‘]=1;mp[‘G‘]=2;mp[‘C‘]=3; 42 n=strlen(a); 43 scanf("%d",&q); 44 int i,j; 45 for (i=1;i<=n;i++) 46 { 47 for (j=1;j<=10;j++) 48 add(i%j,j,mp[a[i-1]],i,1); 49 } 50 while (q--) 51 { 52 int op; 53 scanf("%d",&op); 54 if (op==1) 55 { 56 int x;char ch; 57 scanf("%d %c",&x,&ch); 58 for (i=1;i<=10;i++) 59 { 60 add(x%i,i,mp[a[x-1]],x,-1); 61 add(x%i,i,mp[ch],x,1); 62 } 63 a[x-1]=ch; 64 } 65 else if (op==2) 66 { 67 int ans=0,x,y;char e[15]; 68 scanf("%d %d %s",&x,&y,e); 69 int len=strlen(e); 70 for (i=0;i<len;i++) 71 { 72 ans+=(query((x+i)%len,len,mp[e[i]],y)-query((x+i)%len,len,mp[e[i]],x-1)); 73 } 74 printf("%d ",ans); 75 } 76 } 77 return 0; 78 }
以上是关于一些简单的树状数组题的主要内容,如果未能解决你的问题,请参考以下文章