HDU 4046 Panda (分块 或 线段树区间合并)

题面挺美的
题意:给出一个字符串,两种操作1.询问区间[l,r]内wbw有多少个(可重叠)2.将位置x的字符改为c
题解:分块和线段树都可以搞,分块很好解释,只需要单独处理边界问题。线段树区间合并需要将每次询问的区间拿出来单独处理一次。

分块:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 50005

int n,m;
int num,block,l[maxn],r[maxn],belong[maxn];
char s[maxn];
int ans[maxn];

int solve(int x,int y)
{
    int sum=0;
    for(int i=x;i<=y-2;i++)
    {
        if(s[i]=='w'&&s[i+1]=='b'&&s[i+2]=='w') sum++;
    }
    return sum;
}

void init()
{
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1;i<=n;i++)
    {
        belong[i]=(i-1)/block+1;
    }
    for(int i=1;i<=num;i++)
    {
        l[i]=(i-1)*block+1;
        r[i]=i*block;
    }
    r[num]=n;
    for(int i=1;i<=num;i++)
    {
        ans[i]=solve(l[i],r[i]);
    }
}

void update(int x,char c)
{
    s[x]=c;
    ans[belong[x]]=solve(l[belong[x]],r[belong[x]]);
}

int query(int x,int y)
{
    if(belong[x]==belong[y])
    {
        return solve(x,y);
    }
    int sum=0;
    sum+=solve(x,r[belong[x]]);
    for(int i=belong[x]+1;i<=belong[y];i++)
    {
        if(i!=belong[y]) sum+=ans[i];
        sum+=solve(max(x,l[i]-2),min(y,l[i]+1));
    }
    sum+=solve(l[belong[y]],y);
    return sum;
}

int main()
{
    int ca=1;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        scanf("%s",s+1);
        init();
        printf("Case %d:\n",ca++);
        while(m--)
        {
            int op;
            scanf("%d",&op);
            if(op==0)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                a++,b++;
                printf("%d\n",query(a,b));
            }
            else
            {
                int a;
                char c[3];
                scanf("%d%s",&a,c);
                a++;
                update(a,c[0]);
            }
        }
    }
    return 0;
}

线段树:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f

char s[50005];
int sum[200005];

int Merge(int l,int r)
{
    int mid=l+r>>1;
    int sum=0;
    for(int i=max(mid-1,l);i<=mid;i++)
    {
        if(i+2>r) break;
        if(s[i]=='w'&&s[i+1]=='b'&&s[i+2]=='w') sum++;
    }
    return sum;
}

void init(int l,int r,int k)
{
    if(l==r)
    {
        sum[k]=0;
        return ;
    }
    int mid=l+r>>1;
    init(l,mid,k<<1);
    init(mid+1,r,k<<1|1);
    sum[k]=sum[k<<1]+sum[k<<1|1]+Merge(l,r);
}

void update(char c,int d,int l,int r,int k)
{
    if(l==d&&r==d)
    {
        s[l]=c;
        return ;
    }
    int mid=l+r>>1;
    if(d<=mid) update(c,d,l,mid,k<<1);
    else update(c,d,mid+1,r,k<<1|1);
    sum[k]=sum[k<<1]+sum[k<<1|1]+Merge(l,r);
}

vectorint ,int> >vec;
int query(int s,int t,int l,int r,int k)
{
    if(s==l&&r==t)
    {
        vec.push_back(pair<int ,int>(s,t));
        return sum[k];
    }
    int mid=l+r>>1;
    if(t<=mid) return query(s,t,l,mid,k<<1);
    else if(s>mid) return query(s,t,mid+1,r,k<<1|1);
    else return query(s,mid,l,mid,k<<1)+query(mid+1,t,mid+1,r,k<<1|1);
}

int main()
{
    int T,ca=1;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        scanf("%s",s+1);
        s[0]='#';
        s[n+1]='#';
        s[n+2]='#';
        init(1,n,1);
        printf("Case %d:\n",ca++);
        while(m--)
        {
            int op;
            scanf("%d",&op);
            if(op==0)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                a++;
                b++;
                vec.clear();
                int ans=query(a,b,1,n,1);
                for(int i=0;i1;i++)
                {
                    int x=vec[i].second;
                    for(int j=max(vec[i].first,x-1);j<=x;j++)
                    {
                         if(j+2>b) break;
                         if(s[j]=='w'&&s[j+1]=='b'&&s[j+2]=='w') ans++;
                    }
                }
                printf("%d\n",ans);
            }
            else
            {
                int a;
                char str[3];
                scanf("%d%s",&a,str);
                a++;
                update(str[0],a,1,n,1);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(===数据结构===,线段树,区间合并,分块)