背景:
L
C
T
LCT
LCT的题刷不动了,近几天没有成果,找了一道水题安慰自己…
化学竞赛成功在最后一轮翻车(终于有时间写作业了)。
题目传送门:
https://www.luogu.org/problemnew/show/P5057
题意:
反转一个区间(
0
0
0变
1
1
1,
1
1
1变
0
0
0),求某个元素的值。
思路:
原来的线段树模板太丑了,现在
u
p
d
a
t
e
update
update一下。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int l,r,lc,rc,d,lazy,n;} tr[300010];
int n,m,len=0;
void build(int l,int r)
{
int now=++len,mid=(l+r)>>1;
tr[now]=(node){l,r,-1,-1,0,0,r-l+1};
if(l<r)
{
tr[now].lc=len+1; build(l,mid);
tr[now].rc=len+1; build(mid+1,r);
}
}
void update(int now)
{
if(!tr[now].lazy) return;
int lc=tr[now].lc,rc=tr[now].rc;
if(lc!=-1) tr[lc].lazy+=tr[now].lazy,tr[lc].d+=tr[lc].n*tr[now].lazy;
if(rc!=-1) tr[rc].lazy+=tr[now].lazy,tr[rc].d+=tr[rc].n*tr[now].lazy;
tr[now].lazy=0;
}
void change(int now,int l,int r,int k)
{
update(now);
if(l==tr[now].l&&r==tr[now].r)
{
tr[now].d+=tr[now].n*k;
tr[now].lazy+=k;
return;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)>>1;
if(r<=mid) change(lc,l,r,k);
else if(l>mid) change(rc,l,r,k);
else change(lc,l,mid,k),change(rc,mid+1,r,k);
tr[now].d=tr[lc].d+tr[rc].d;
}
int findsum(int now,int l,int r)
{
update(now);
if(l==tr[now].l&&r==tr[now].r) return tr[now].d;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)>>1;
if(r<=mid) return findsum(lc,l,r);
else if(l>mid) return findsum(rc,l,r);
else return findsum(lc,l,mid)+findsum(rc,mid+1,r);
}
int main()
{
int t,x,y;
scanf("%d %d",&n,&m);
build(1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&t);
switch(t)
{
case 1:scanf("%d %d",&x,&y);change(1,x,y,1);break;
case 2:scanf("%d",&x);printf("%d\n",findsum(1,x,x)&1);break;
}
}
}