Description
一辆自动驾驶的出租车正在 Innopolis 的街道上行驶。该街道上有 $n+1$ 个停车站点,它们将街道划分成了 $n$ 条路段。每一路段都拥有一个路灯。当第 $i$ 个路灯亮起,它将照亮连接第 $i$ 与第 $i+1$ 个站点的路段。否则这条路段将是黑暗的。
安全起见,出租车只能在被照亮的路段上行驶。换言之,出租车能从站点 $a$ 出发到达站点 $b(a < b)$ 的条件是:连接站点 $a$ 与 $a+1,a+2 cdots b-1$ 与 $b$ 的路段都被照亮。
在经过一些意外故障或修理之后,街道上的路灯可能是亮起的,也可能是熄灭的。
现在给定 $0$ 时刻时,街道上路灯的初始状态。之后 $1,2,ldots,q$ 时刻,每时刻会发生下列两种事件之一:
toggle i:切换第 $i$ 个路灯的状态。具体地说,若路灯原来亮起,则现在将熄灭;若路灯原来熄灭,则现在将亮起。
query a b:出租车部门的负责人想知道,从 $a$ 时刻起到当前时刻,有多少个时刻满足:出租车能够从站点 $a$ 出发到达站点 $b$。
请你帮助出租车部门的负责人回答他们的问题。
Solution
点亮一个路灯即为连接两个明亮的路段,维护所有明亮的路段可以使用set
维护答案时,若连接$(l_1,r_1)$和$(l_2,r_2)$,那么对于区间$[l_1cdots l_2,r_1cdots r_2]$,区间由暗变亮了,相当于矩形区间加$q-t$,$t$为此时时间
熄灭路灯同理,求答案时相当于单点求值,若此时整个区间仍然明亮,答案需要减去$q-t$
#include<iostream> #include<cstdio> #include<set> using namespace std; int n,q,rt[300005],cnt; char str[300005],opt[10]; struct Node{ int l,r; bool operator <(const Node &z)const{return r<z.r;} }; struct SGT{ int lc,rc,val; }tr[30000005]; set<Node>s; inline int read(){ int f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } void update(int &i,int l,int r,int p,int v){ if(!i)i=++cnt; tr[i].val+=v; if(l==r)return; int mid=l+r>>1; if(p<=mid)update(tr[i].lc,l,mid,p,v); else update(tr[i].rc,mid+1,r,p,v); } int query(int i,int l,int r,int L,int R){ if(!i)return 0; if(L<=l&&r<=R)return tr[i].val; int mid=l+r>>1,ret=0; if(L<=mid)ret+=query(tr[i].lc,l,mid,L,R); if(R>mid)ret+=query(tr[i].rc,mid+1,r,L,R); return ret; } void add(int pos,int y,int v){while(pos<=n+2)update(rt[pos],1,n+2,y,v),pos+=pos&-pos;} void solve(int x1,int y1,int x2,int y2,int v){add(x1,y1,v),add(x2+1,y2+1,v),add(x1,y2+1,-v),add(x2+1,y1,-v);} int ask(int x,int y){ int ret=0; while(x)ret+=query(rt[x],1,n+2,1,y),x-=x&-x; return ret; } int main(){ n=read(),q=read(),scanf("%s",str+1); for(int i=1;i<=n+1;i++)s.insert((Node){i,i}); for(int i=1;i<=n;i++)if(str[i]=='1'){ set<Node>::iterator it=s.lower_bound((Node){0,i}); int l=(*it).l; s.erase(it),s.erase((Node){i+1,i+1}),s.insert((Node){l,i+1}); } for(set<Node>::iterator it=s.begin();it!=s.end();it++)solve((*it).l,(*it).l,(*it).r,(*it).r,q); for(int i=1;i<=q;i++){ scanf("%s",opt); if(opt[0]=='t'){ int x=read(); if(str[x]=='1'){ set<Node>::iterator it=s.lower_bound((Node){0,x}); int l1=(*it).l,r1=x,l2=x+1,r2=(*it).r; solve(l1,l2,r1,r2,i-q),s.erase(it),s.insert((Node){l1,r1}),s.insert((Node){l2,r2}),str[x]='0'; } else{ set<Node>::iterator it=s.lower_bound((Node){0,x}); int l1=(*it).l,r1=x,l2=x+1,r2=0; ++it,l2=x+1,r2=(*it).r,solve(l1,l2,r1,r2,q-i),s.erase(it),s.erase((Node){l1,r1}),s.insert((Node){l1,r2}),str[x]='1'; } } else{ int x=read(),y=read(),ans=ask(x,y); set<Node>::iterator it1=s.lower_bound((Node){0,x}),it2=s.lower_bound((Node){0,y}); printf("%d ",ans-(q-i)*((*it1).l==(*it2).l)); } } return 0; }