Lightoj1080 【线段树】
题意:
给你一个0/1的数组,然后给你n段区间,说这个区间里要反转一次,然后给你Q个询问,问你这个位置是什么;
思路:
我们线段树维护一下就好了额;
给你一个0/1的数组,然后给你n段区间,说这个区间里要反转一次,然后给你Q个询问,问你这个位置是什么;
思路:
我们线段树维护一下就好了额;
其实反转的话,还是算次数是不是,奇偶嘛;
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e5+10; struct SegT{ int sum; int val; int left; int right; }; SegT q[N*4]; char id[N]; void Build(int num,int L ,int R) { q[num].left=L; q[num].right=R; q[num].val=0; q[num].sum=0; if(L==R) return; int mid=(L+R)>>1; Build(2*num,L,mid); Build(2*num+1,mid+1,R); } void PushDown(int num) { if(q[num].val) { q[2*num].sum+=(q[2*num].right - q[2*num].left+1)*q[num].val; q[2*num].val+=q[num].val; q[2*num+1].sum+=(q[2*num+1].right - q[2*num+1].left+1)*q[num].val; q[2*num+1].val+=q[num].val; q[num].val=0; } } void Update(int num,int s,int t) { if(q[num].left>=s&&q[num].right<=t) { q[num].sum+=(q[num].right - q[num].left+1); q[num].val+=1; return; } PushDown(num); int mid=(q[num].left+q[num].right)>>1; if(mid>=t) Update(2*num,s,t); else if(mid<s) Update(2*num+1,s,t); else { Update(2*num,s,mid); Update(2*num+1,mid+1,t); } q[num].sum=q[2*num].sum+q[2*num+1].sum; } int query(int num,int x) { if(q[num].left==q[num].right&&q[num].left==x) return q[num].sum; PushDown(num); int mid=(q[num].left+q[num].right)>>1; if(mid>=x) return query(2*num,x); else return query(2*num+1,x); } int main() { int T,cas=1,n; scanf("%d",&T); while(T--) { scanf("%s",id+1); n=strlen(id+1); Build(1,1,n); int Q,x,y; char tx[3]; scanf("%d",&Q); printf("Case %d:\n",cas++); while(Q--) { scanf("%s",tx); if(tx[0]=='I') { scanf("%d%d",&x,&y);//已经保证 1 ≤ i ≤ j ≤ n.; Update(1,x,y); } else { scanf("%d",&x); printf("%d\n",query(1,x)%2==0?(id[x]-'0'):(1-id[x]+'0')); } } } return 0; }