题意:给一些结点,每个结点是黑色或白色,并有一个权值。定义两个结点之间的距离为两个结点之间结点的最小权值当两个结点异色时,否则距离为无穷大。给出两种操作,一种是将某个结点改变颜色,另一个操作是询问当前距离小于K的结点有多少对,K是一个定值。
思路:先求最初时候小于k的结点有多少对,然后每次改变颜色的时候,统计该点左侧和右侧各有多少同色和异色的结点(这一步使用树状数组),分别处理就行。另外需要预处理离某个结点最近的两个距离小于K的结点的位置。
代码写的略乱。
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<time.h> #include<iostream> #define INF 10000000 #define LL long long using namespace std; int n,K; vector<int> vec; ]; struct BIT { ]; void clear() { memset(dat,,sizeof(dat)); } int lowBit(int x) { return -x&x; } int getSum(int x) { ; ) { s+=dat[x]; x-=lowBit(x); } return s; } void addVal(int x,int c) { ) return; while(x<=n) { dat[x]+=c; x+=lowBit(x); } } void setVal(int x,int c) { ); addVal(x,-old+c); } int getCol(int x) { ); } int countBlack(int ql,int qr) { ; ); } int countWhite(int ql,int qr) { ; int s=countBlack(ql,qr); -s; } }; BIT tree; ],rightM[]; int main() { int T; scanf("%d",&T); while(T--) { int m; scanf("%d%d%d",&n,&m,&K); vec.clear(); ; i<=n; ++i) { int val; scanf("%d",&val); if(val<K) vec.push_back(i); } tree.clear(); ; i<=n; ++i) { int val; scanf("%d",&val); tree.setVal(i,val); ; int r=lower_bound(vec.begin(),vec.end(),i)-vec.begin(); ) leftM[i]=-; else leftM[i]=vec[l]; ; else rightM[i]=vec[r]; } LL sum=; ,end; ; i<vec.size(); ++i) { last=(i==)?:vec[i-]+; end=(i==vec.size()-)?n:vec[i+]; LL lb=tree.countBlack(last,vec[i]-),rw=tree.countWhite(vec[i]+,n); LL lw=tree.countWhite(last,vec[i]-),rb=tree.countBlack(vec[i]+,n); sum+=lb*rw; sum+=lw*rb; int col=tree.getCol(vec[i]); ) sum+=lb+rb; else sum+=lw+rw; } while(m--) { int p; scanf("%d",&p); ) printf("%I64d\n",sum); else { int x; scanf("%d",&x); int old=tree.getCol(x); ) { ) { LL lw,lb; if(leftM[x]==x) { lw=tree.countWhite(,leftM[x]-); lb=tree.countBlack(,leftM[x]-); } else { lw=tree.countWhite(,leftM[x]); lb=tree.countBlack(,leftM[x]); } sum-=lw; sum+=lb; } ) { LL rw,rb; if(rightM[x]==x) { rb=tree.countBlack(rightM[x]+,n); rw=tree.countWhite(rightM[x]+,n); } else { rb=tree.countBlack(rightM[x],n); rw=tree.countWhite(rightM[x],n); } sum-=rw; sum+=rb; } } else { ) { LL lw,lb; if(leftM[x]==x) { lw=tree.countWhite(,leftM[x]-); lb=tree.countBlack(,leftM[x]-); } else { lw=tree.countWhite(,leftM[x]); lb=tree.countBlack(,leftM[x]); } sum+=lw; sum-=lb; } ) { LL rw,rb; if(rightM[x]==x) { rb=tree.countBlack(rightM[x]+,n); rw=tree.countWhite(rightM[x]+,n); } else { rb=tree.countBlack(rightM[x],n); rw=tree.countWhite(rightM[x],n); } sum+=rw; sum-=rb; } } tree.setVal(x,old^); } } } ; }