AC dreamoj 1011 树状数组+hash维护字符串的前缀和

http://acdream.info/problem?pid=1019

Problem Description

Now we have a long long string, and we will have two kinds of operation on it.

C i y : change the ith letter to y.

Q i j : check whether the substring from ith letter to jth letter is a palindrome.

Input

There are multiple test cases.

The first line contains a string whose length is not large than 1,000,000.

The next line contains a integer N indicating the number of operations.

The next N lines each lines contains a operation.

All letters in the input are lower-case.

Output

For each query operation, output "yes" if the corresponding substring is a palindrome, otherwise output "no".

Sample Input

aaaaa
4
Q 1 5
C 2 b
Q 1 5
Q 1 3

Sample Output

yes
no
yes
/**
ACdreamoj 1019  树状数组+hash维护字符串的前缀和
题目大意:
         给定一个字符串,单点更新,区间查询该区间是不是回文串。
解题思路:
         hash是x1 * p^1+ x2*p^2 +x3*p^3...可以用树状数组维护前缀和,
维护两个串,一个是正串,另一个是反串用于比较。
字符串区间s[l~r]的哈希值为sum(s[r]-s[l-1])/Hash[l-1];
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long LL;
const int maxn=1000010;
const int seed=13;

LL Hash[maxn],C[2][maxn];
char s[maxn];
int len;

void init()
{
    Hash[0]=1;
    for(int i=1;i<maxn;i++)
         Hash[i]=Hash[i-1]*seed;
}

int lowbit(int x)
{
    return x&(-x);
}

void add(int i,int x,LL pos)
{
    while(x<=len)
    {
        C[i][x]+=pos;
        x+=lowbit(x);
    }
}

LL sum(int i,int x)
{
    LL ans=0;
    while(x)
    {
        ans+=C[i][x];
        x-=lowbit(x);
    }
    return ans;
}
LL gethash(int i,int l,int r)
{
    return sum(i,r)-sum(i,l-1);
}
int main()
{
     init();
     while(~scanf("%s",s+1))
     {
         memset(C,0,sizeof(C));
         len=strlen(s+1);
         for(int i=1;i<=len;i++)
         {
             add(0,i,(s[i]-'a')*Hash[i]);
             add(1,len+1-i,(s[i]-'a')*Hash[len+1-i]);
         }
         int T;
         cin >> T;
         while(T--)
         {
             char c[5];
             scanf("%s",c);
             if(c[0]=='C')
             {
                 char b[5];
                 int a;
                 scanf("%d%s",&a,b);
                 add(0,a,(b[0]-s[a])*Hash[a]);
                 add(1,len+1-a,(b[0]-s[a])*Hash[len+1-a]);
                 s[a]=b[0];
             }
             else
             {
                 int l,r;
                 scanf("%d%d",&l,&r);
                 if(gethash(0,l,r)*Hash[len-r]==gethash(1,len+1-r,len+1-l)*Hash[l-1])//采用交叉相乘把除换成了乘
                      puts("yes");
                 else
                      puts("no");
             }
         }
     }
     return 0;
}
时间: 2024-11-07 19:00:51

AC dreamoj 1011 树状数组+hash维护字符串的前缀和的相关文章

hdu 4368 树状数组 离线维护

http://acm.hdu.edu.cn/showproblem.php?pid=4638 Problem Description There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-1 are friends, Whose ID is i and i+1 are friends. These n men stand in line. Now we select an interv

bzoj 1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛【dp+树状数组+hash】

最长上升子序列.虽然数据可以直接n方但是另写了个nlogn的 转移:f[i]=max(f[j]+1)(a[j]<a[i]) O(n^2) #include<iostream> #include<cstdio> using namespace std; const int N=5005; int n,a[N],f[N],ans; int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(

ACdreamoj 1011(树状数组维护字符串hash前缀和)

题目链接:http://acdream.info/problem? pid=1019 题意:两种操作,第一种将字符串某个位置的字符换为还有一个字符.另外一种查询某个连续子序列是否是回文串: 解法:有两种hash的办法,所以写了两种解法;首先hash是x1 * p^1+ x2*p^2 +x3*p^3...能够用树状数组维护前缀和,维护两个串,一个是正串.还有一个是反串用于比較.比較时候乘以对应的p倍数推断是否相等. 刘汝佳白书上的hash方法处理这道题更复杂:改动i会对后缀j产生的影响为a*p^(

bzoj2124 等差子序列(树状数组+hash)

题意 给你一个1~n排列,问有没有一个等差数列(长度至少为3) 题解 我居然自己想到了正解. 但我最后写挂了,所以我又看了题解. 我们维护了一个以权值为下标的01序列. 我们扫描整个序列.对于每一个正在扫描的数,我们判断以这个数的权值作为对称点,01序列是否对称. 这个序列用权值树状数组维护就行. 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #

Codeforces Round #227 (Div. 2)---E. George and Cards(贪心, 树状数组+set维护, 好题!)

George is a cat, so he loves playing very much. Vitaly put n cards in a row in front of George. Each card has one integer written on it. All cards had distinct numbers written on them. Let's number the cards from the left to the right with integers f

HDU 5465——Clarke and puzzle——————【树状数组BIT维护前缀和+Nim博弈】

Clarke and puzzle Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 673    Accepted Submission(s): 223 Problem Description Clarke is a patient with multiple personality disorder. One day, Clarke s

AtCoder Regular Contest 075 E - Meaningful Mean 树状数组求顺序对, 前缀和

题目链接: http://arc075.contest.atcoder.jp/tasks/arc075_c 题意: 给你一个序列和一个数k,求有多少对l,r,使得a[l]+a[l+1]+...+a[r]的算术平均数大于等于k 1≤N≤2×10^5 1≤K≤10^9 1≤ai≤10^9 思路: 首先对于所有数减去k,这样就不用除(r-l+1), 然后我们发现所求的就是有多少对l,r,使得sum[r]-sum[l-1] >= 0, sum是减去k之后的序列的前缀和 用树状数组对sum求有多少个顺序对

POJ3468(树状数组区间维护)

模板题 #include"cstdio" #include"cstring" #define lowbit(i) i&(-i) using namespace std; const int MAXN=100005; typedef long long LL; LL bit0[MAXN]; LL bit1[MAXN]; void add(LL* b,int i,int c) { while(i<=MAXN) { b[i]+=c; i+=lowbit(i)

BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status][Discuss] Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据.    输入的第一行一个整数Q表示测试点内的数据