一些简单的树状数组题

题目链接: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 }

 

 
posted @ 2018-10-12 11:53  EncodeTalker  阅读(344)  评论(0编辑  收藏  举报