145E:Lucky Queries
题意简述
维护一个只有数字
4
和
1.将
[l,r]
区间
4
变为
2.询问全局最长不下降子序列的长度。
输出所有2操作的答案
思路
线段树维护。
维护四个信息:
1.区间
4
的个数。
2.区间
3.区间不降子序列的长度。
4.区间不升子序列的长度。
代码
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,u,v;
char seq[1000010],opt[10];
namespace Segtree
{
struct Node{
int f,s,fs,sf,rev;
}tree[4000010];
void pushup(int node)
{
tree[node].f=tree[node<<1].f+tree[node<<1|1].f;
tree[node].s=tree[node<<1].s+tree[node<<1|1].s;
tree[node].fs=max(tree[node<<1].f+tree[node<<1|1].fs,tree[node<<1].fs+tree[node<<1|1].s);
tree[node].sf=max(tree[node<<1].s+tree[node<<1|1].sf,tree[node<<1].sf+tree[node<<1|1].f);
}
void pushdown(int node)
{
if (tree[node].rev)
{
swap(tree[node<<1].s,tree[node<<1].f);
swap(tree[node<<1].sf,tree[node<<1].fs);
tree[node<<1].rev^=1;
swap(tree[node<<1|1].s,tree[node<<1|1].f);
swap(tree[node<<1|1].sf,tree[node<<1|1].fs);
tree[node<<1|1].rev^=1;
tree[node].rev=0;
}
}
void build(int l,int r,int node)
{
if (l==r)
{
if (seq[l]=='4')
tree[node].f=tree[node].sf=tree[node].fs=1;
else
tree[node].s=tree[node].sf=tree[node].fs=1;
return;
}
int mid=(l+r)>>1;
build(l,mid,node<<1);
build(mid+1,r,node<<1|1);
pushup(node);
}
void modify(int L,int R,int l,int r,int node)
{
if (L<=l&&r<=R)
{
tree[node].rev^=1;
swap(tree[node].s,tree[node].f);
swap(tree[node].sf,tree[node].fs);
return;
}
pushdown(node);
int mid=(l+r)>>1;
if (L<=mid)
modify(L,R,l,mid,node<<1);
if (R>mid)
modify(L,R,mid+1,r,node<<1|1);
pushup(node);
}
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",seq+1);
Segtree::build(1,n,1);
for (int i=1;i<=m;i++)
{
scanf("%s",opt);
if (opt[0]=='c')
printf("%d\n",Segtree::tree[1].fs);
else
{
scanf("%d%d",&u,&v);
Segtree::modify(u,v,1,n,1);
}
}
return 0;
}