[洛谷P3948]数据结构
题目大意:有n个数,opt个操作,并给你md、min、max。
每种操作有以下两种:1.给一段区间加一个固定值。2.询问一段区间内满足$min\leq T*i\ mod\ md\leq max$(T是当前的数,i是当前数的下标)的数的个数。
在这opt个操作里,询问不超过1000个。
这之后还有final($<10^7$)个询问(同上面的询问),保证这些询问中间没有修改操作。
要你实现这些操作。
解题思路:一开始被这些巨大的数据唬住了,经过思考看了标程后突然发现并不是很难。
对于区间和操作,很容易想到差分解决,但中间还有询问操作,怎么办?
题目说中间最多1000个询问,而n最大才80000,对于每一个询问,都扫描一遍差分数组的话,不考虑常数则要执行大约80000000次操作。
但标程告诉我这样是可以卡过去的(洛谷神评测机)。
再来考虑后面的询问,由于没有了修改操作,我们可以维护一个前缀和,来实现$O(1)$询问。
然后就玄学地卡了过去。
C++ Code:
#include<cstdio> #include<cctype> #include<cstring> #define ll long long int n,opt,mod,min,max,l,r,b[80003]; ll a[80003]; char c; inline int readint(){ char c=getchar(); bool b=false; for(;!isdigit(c);c=getchar())b=c=='-'; int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^'0'); return b?-d:d; } inline void putint(int p){ if(p==0){ putchar('0'); putchar('\n'); return; } int w=1; while(w<=p)w*=10;w/=10; while(w){ putchar(p/w+'0'); p%=w; w/=10; } putchar('\n'); } int main(){ n=readint(),opt=readint(),mod=readint(),min=readint(),max=readint(); memset(a,0,sizeof a); while(opt--){ for(c=getchar();!isalpha(c);c=getchar()); l=readint(),r=readint(); if(c=='A'){ int num=readint(); a[l]+=num,a[r+1]-=num; }else{ int cnt=0; ll sum=0; for(int i=1;i<=r;++i){ sum+=a[i]; if(i>=l)cnt+=(int)(sum%mod*i%mod>=min&&sum%mod*i%mod<=max); } putint(cnt); } } b[0]=0; ll sum=0; for(int i=1;i<=n;++i){ sum+=a[i]; b[i]=b[i-1]+(int)(sum%mod*i%mod>=min&&sum%mod*i%mod<=max); } for(int final=readint();final--;){ l=readint(),r=readint(); putint(b[r]-b[l-1]); } return 0; }