Problem Description
You are given a array with N nodes. The array nodes are numbered from 1 to N ( represented by a_i ). In the start, the color
of any node in the array is white or black. We define that the "distance" between a and b is min{a_i| a<=i<=b} if a-th and bth
nodes have diffrerent color, or infinite if they have the same color.
We will ask you to perfrom some instructions of the following form:
0 i : change the color of the i-th node (from white to black, or from black to white);
or
1 : ask for the kinds of diffrent pair of nodes' distance is less than K
of any node in the array is white or black. We define that the "distance" between a and b is min{a_i| a<=i<=b} if a-th and bth
nodes have diffrerent color, or infinite if they have the same color.
We will ask you to perfrom some instructions of the following form:
0 i : change the color of the i-th node (from white to black, or from black to white);
or
1 : ask for the kinds of diffrent pair of nodes' distance is less than K
Input
The first line contains a positive integer: the number of test cases, at most 100.
After that per test case:
One line with three integers N, m and K (1 ≤ N, m ≤ 1 00000, K ≤ 1000000): the length of the array, the number of
instructions and K which used in operation 1 .
Then comes a line with N intergers a_i (|a_i|<10000000).
A line with N intergers c_i (c_i = 0(white) or 1(black)), which reprsent the color of N nodes.
Next m lines, each will be a instruction described above.
After that per test case:
One line with three integers N, m and K (1 ≤ N, m ≤ 1 00000, K ≤ 1000000): the length of the array, the number of
instructions and K which used in operation 1 .
Then comes a line with N intergers a_i (|a_i|<10000000).
A line with N intergers c_i (c_i = 0(white) or 1(black)), which reprsent the color of N nodes.
Next m lines, each will be a instruction described above.
Output
one interger for each operation 1.
Sample Input
1 5 3 2 2 3 1 4 2 0 1 0 1 1 1 0 2 1
Sample Output
5 6
//
题目描述:
给你n个数,和每个数字的状态(0或者1)。
有两种操作:
第一种:翻转某个数字的状态。
第二种:询问,要求输入满足条件的i, j组合个数。
一个满足条件的i,j要求:
A:1 <= i <= j <= n
B: i和j数字的状态不同
C:i和j的闭区间内的数字的最小值小于k(k由输入给定)
解题报告:
对于一开始的输入先求出组合个数。
然后对于每次的翻转状态,更新组合个数:
比如翻转i,如果x[i] < k, 那么只需看i左侧有多少个0或者1(具体看x[i]当前状态),和i右侧有多少个0或者1(同上),就可以知道这次翻转具体变化了多少,具体的实现可以用树状数组。
如果x[i] > k,初始化时记下在i左侧最近的小于k的数字的位置L[i],同理R[i]。
找到L[i]左侧0或者1的个数和R[i]右侧0或者1的个数,就是这次变化的个数。
应该比较好理解。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<cmath> #include<string> #include<cstring> #include<set> #include<map> #include<list> #include<queue> #include<vector> #define tree int o,int l,int r #define lson o<<1,l,mid #define rson o<<1|1,mid+1,r #define lo o<<1 #define ro o<<1|1 #define ULL unsigned long long #define LL long long #define inf 0x7fffffff #define eps 1e-7 #define N 100009 using namespace std; int T,n,m,k,t,maxv,x; int cl[N],c[N]; int l[N],r[N]; bool val[N]; LL ans; void init() { ans=0; memset(c,0,sizeof(c)); memset(cl,0,sizeof(cl)); } void add(int x,int v) { while(x<N) { c[x]+=v; x+=x&-x; } } int sum(int x) { int ans=0; while(x>0) { ans+=c[x]; x-=x&-x; } return ans; } int main() { #ifndef ONLINE_JUDGE freopen("ex.in","r",stdin); #endif scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&k); init(); for(int i=1; i<=n; i++) { scanf("%d",&x); if(x<k) val[i]=0; else val[i]=1; } for(int i=1; i<=n; i++) { scanf("%d",&cl[i]); if(cl[i]) add(i,cl[i]); } int x=0; for(int i=1; i<=n; i++) { if(val[i]==0) { for(int j=i-1; j>x; j--) l[j]=x,r[j]=i; x=i; l[i]=i; r[i]=i;///// } } for(int j=x+1; j<=n; j++) l[j]=x,r[j]=n+1; for(int i=1; i<=n; i++) { if(val[i]==0)// { ans+=i-1; t=i-1; } else { ans+=l[i]; t=l[i]; } int num=sum(t),all=t; if(cl[i]==1) { t=num; } else t=(all-num); ans-=t; } while(m--) { scanf("%d",&x); if(x) { printf("%I64d\n",ans); } else { scanf("%d",&x); // cout<<"x="<<x<<endl; if(val[x]==0) { // cout<<"========"<<endl; int num=sum(n),t,all=n-1; if(cl[x]==1) { num--; // cout<<"num="<<num<<endl; t=num-(all-num); } else t=(all-num)-num; ans+=t; } else { int t,all=n-(r[x]-l[x]-1); int num=sum(n)-sum(r[x]-1)+sum(l[x]); if(cl[x]==1) { t=num-(all-num); } else t=(all-num)-num; ans+=t; } cl[x]=!cl[x]; if(!cl[x]) add(x,-1); else add(x,1); } } } return 0; }