[LOJ#3146] [APIO 2019]光(セットツリーツリー)
フェイス質問
問題の解決策
診察室あるため、\(\テキスト{橋} \ ) \(\テキスト{サブタスク} \ ) がない文\(N = 1 \)の状況は私にカードつながった\(3.5時間\)またはそう、この問題は希望をラッシュのみ\(ラッシュ\)\(60 \)ポイントの暴力......
連続セグメントについて、その後、各時間ランプを明るい連続セグメントを維持考える\([L、R&LT] \) 、これは明らかに、任意の設定時間間隔が寄与して生成される照会します。
連続期間を維持することに対処することは非常に困難であるので、ライトをオンにすると、それぞれの場所の影響を考慮していませんでしたので。
仮定\(X \)の位置が回転しない、開いた位置ではない\(LTの\) 、次いで左間隔の\([LT + 1、I] \)、右間隔\([LT + 1 、i]は\)寄与の範囲内で生成され、その後、我々は、間隔点に置くので、二次元の点の数に寄与することができます。
だから、ライン上で直接木カバーツリーのメンテナンスを取ります。(または、\(CDQ \)などでもOKです)
、ここで使用される統計方法は、差動答えに似ている、我々は上のすべての場所へのスタートを与えた\(+ Q \) 、操作を変更するために貢献貢献の影響の範囲をうまく補うために。
例えば、もしくは\(X \)と\(LT \)二つの位置、左間隔\([+のLT。1、I] \) 、右間隔\([I + 1、N + 1] \)何の貢献を間隔ません。
次いでする\((LT + 1、I + 1)\) 位置プラス\( - Qの\)、\ ((1 + I、+ I. 1)\)場所プラス\(Q \)は、この貢献の外にサービスを提供することができます。
統計答えは、現在のちょうど完全な範囲であれば、答えを覚えている最後の時間を、私たちは時間の残りカウントしてはいけません\(Q \)を取り除くための時間を。。。
#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
#define MAX 300300
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,Q;
struct Node{int ls,rs,v;}t[MAX<<6];
int tot,rt[MAX];
void Modify(int &x,int l,int r,int p,int w)
{
if(!x)x=++tot;t[x].v+=w;
if(l==r)return;
int mid=(l+r)>>1;
if(p<=mid)Modify(t[x].ls,l,mid,p,w);
else Modify(t[x].rs,mid+1,r,p,w);
}
int Query(int x,int l,int r,int L,int R)
{
if(!x)return 0;
if(L<=l&&r<=R)return t[x].v;
int mid=(l+r)>>1,ret=0;
if(L<=mid)ret+=Query(t[x].ls,l,mid,L,R);
if(R>mid)ret+=Query(t[x].rs,mid+1,r,L,R);
return ret;
}
int lb(int x){return x&(-x);}
void Modify(int x,int y,int v){while(x<=n+1)Modify(rt[x],1,n+1,y,v),x+=lb(x);}
int Query(int x,int y){int s=0;while(x)s+=Query(rt[x],1,n+1,1,y),x-=lb(x);return s;}
set<int> S;set<int>::iterator it,pr,nt;
char ch[MAX];
int main()
{
n=read();Q=read();scanf("%s",ch+1);
S.insert(0);S.insert(n+1);Modify(1,1,Q);
for(int i=1,j=0;i<=n;++i)
{
if(ch[i]=='1')continue;
S.insert(i);
Modify(j+1,i+1,-Q);
Modify(i+1,i+1,Q);
j=i;
}
while(Q--)
{
char opt[8];scanf("%s",opt);
if(opt[0]=='t')
{
int x=read(),zt=(ch[x]=='0')?1:-1;
if(ch[x]=='1')S.insert(x);
it=S.find(x);
pr=nt=it;--pr;++nt;
Modify(*pr+1,x+1,Q*zt);Modify(x+1,x+1,-Q*zt);
if(*nt!=n+1)Modify(*pr+1,*nt+1,-Q*zt),Modify(x+1,*nt+1,Q*zt);
if(ch[x]=='0')S.erase(x);
ch[x]^=1;
}
else
{
int x=read(),y=read();
printf("%d\n",Query(x,y)-Q*(S.lower_bound(x)==S.lower_bound(y)));
}
}
return 0;
}