HZAU 1207 Candies(线段树区间查询 区间修改)

【题目链接】http://acm.hzau.edu.cn/problem.php?id=1207

【题意】给你一个字符串,然后两种操作:1,将区间L,R更新为A或者B,2,询问区间L,R最长的连续的B为多长。

【分析】典型线段树,每个节点维护该区间左边连续B的长度,右边连续B的长度,最长的连续B的长度,还有lazy标记。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <string>
#include <cmath>
#include <stdlib.h>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int N=1e6+10;
int n,m,k,L,R,V;
char s[N];
int lazy[N<<2];
struct Tree{
    int l,r,maxn,len;
}a[N<<2];
void pushdwn(int pos,int len){
    if(lazy[pos]!=-1){
        lazy[pos<<1]=lazy[pos<<1|1]=lazy[pos];
        a[pos<<1].l=a[pos<<1].r=a[pos<<1].maxn=lazy[pos]?len-(len>>1):0;
        a[pos<<1|1].l=a[pos<<1|1].r=a[pos<<1|1].maxn=lazy[pos]?(len>>1):0;
        lazy[pos]=-1;
    }
}
void pushup(int pos,int len){
    a[pos].l=a[pos<<1].l;
    a[pos].r=a[pos<<1|1].r;
    if(a[pos].l==len-(len>>1))a[pos].l+=a[pos<<1|1].l;
    if(a[pos].r==(len>>1))a[pos].r+=a[pos<<1].r;
    a[pos].maxn=max(a[pos<<1].r+a[pos<<1|1].l,max(a[pos<<1].maxn,a[pos<<1|1].maxn));
}
void build(int pos,int l,int r){
    lazy[pos]=-1;
    if(l==r){
        a[pos].l=a[pos].r=a[pos].maxn=(s[l]==‘B‘)?1:0;
        return;
    }
    int mid=(l+r)>>1;
    build(pos<<1,l,mid);
    build(pos<<1|1,mid+1,r);
    pushup(pos,r-l+1);
}
void update(int pos,int l,int r){
    if(L<=l&&r<=R){
        a[pos].l=a[pos].r=a[pos].maxn=V?r-l+1:0;
        lazy[pos]=V;
        return;
    }
    pushdwn(pos,r-l+1);
    int mid=(l+r)>>1;
    if(L<=mid)update(pos<<1,l,mid);
    if(R>mid)update(pos<<1|1,mid+1,r);
    pushup(pos,r-l+1);
}
Tree merg(Tree t1,Tree t2){
    Tree ret;
    ret.len=t1.len+t2.len;
    ret.l=t1.l;
    ret.r=t2.r;
    if(t1.l==t1.len) ret.l+=t2.l;
    if(t2.r==t2.len) ret.r+=t1.r;
    ret.maxn=max(t1.r+t2.l,max(t1.maxn,t2.maxn));
    return ret;
}
Tree query(int pos,int l,int r){
    if(L<=l&&r<=R){
        a[pos].len=r-l+1;
        return a[pos];
    }
    pushdwn(pos,r-l+1);
    int mid=(l+r)>>1;
    if(mid>=R)return query(pos<<1,l,mid);
    if(mid<L)return query(pos<<1|1,mid+1,r);
    Tree t1=query(pos<<1,l,mid),t2=query(pos<<1|1,mid+1,r);
    return merg(t1,t2);
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {
        memset(a,0,sizeof a);
        printf("Case #%d:\n",cas);
        scanf("%d%d%s",&n,&m,s+1);
        build(1,1,n);
        int p;
        while(m--)
        {
            scanf("%d%d%d",&p,&L,&R);
            if(p==1)
            {
                scanf("%d",&V);
                V--;
                update(1,1,n);
            }
            else printf("%d\n",query(1,1,n).maxn);
        }
    }
    return 0;
}
时间: 2024-10-11 00:08:59

HZAU 1207 Candies(线段树区间查询 区间修改)的相关文章

hihoCode 1078 : 线段树的区间修改

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

hiho一下20周 线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

线段树的区间修改

线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格--小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问--小Hi给出一段区间[L, R]

hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

模板 线段树的区间修改

线段树的区间修改 区间绝对标记 改成同一个数 注意打标记前 要先判断 是否有标记 这道题不能像加法标记一样 标记初始化为 0 如果这道题 可以将数变成 0 那么0 就不能为初始值了 然后我们初始值要选择一个不会被干扰到的数字 比如 -1 就不会变成 -1 另外还要注意在标记清空时 要将标记 变成 -1 而不是 0 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstr

POJ 2828 Buy Tickets (线段树,区间修改)

逆向思维.从最后一位开始考虑,用线段树查询空位置. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include &l

线段树 (区间修改 区间查询 延迟标记)

hdu 1698 Just a Hook 题意: 给你一链子,这天链子由金银铜三种钩子组成,每种钩子都有自己的价值,起初,这条钩子全部由铜钩子组成,给你两个数n(钩子的个数),Q(操作的个数)每次操作就是将给定区间里的数变成某种钩子,求这条链子的总价值. 分析: 线段树模版题,处理好延迟标记即可. 代码: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #in

[线段树模板] 区间修改 区间查询(详注)

输入 每个测试点(输入文件)有且仅有一组测试数据. 每组测试数据的第1行为一个整数N,意义如前文所述. 每组测试数据的第2行为N个整数,分别描述每种商品的重量,其中第i个整数表示标号为i的商品的重量Pi. 每组测试数据的第3行为一个整数Q,表示小Hi进行的操作数. 每组测试数据的第N+4~N+Q+3行,每行分别描述一次操作,每行的开头均为一个属于0或1的数字,分别表示该行描述一个询问和一次商品的价格的更改两种情况.对于第N+i+3行,如果该行描述一个询问,则接下来为两个整数Li, Ri,表示小H