1. 程式人生 > >一些簡單的樹狀數組題

一些簡單的樹狀數組題

lan else char esp %s clas https 組成 長度

題目鏈接:CF961E

大意:給定一列數$a_i$,求滿足下列條件的數對$(x,y)$的數量:$(1)x<y,(2)a_x\geq y,(3)a_y\geq 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$(即這個字符串為$ee\ldots$),將它與原字符串的子串$[l\ldots r]$進行比較,求出有多少位能夠匹配

本題的關鍵在於$e\leq 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\n",ans);
75         }
76     }
77     return 0;
78 }

一些簡單的樹狀數組題