标签:
莫队算法
今天为了做这道题先去学了莫队算法,然后A掉了莫队算法的入门题目——小Z的袜子。
考场上面我傻逼的打了一个高精度,华丽丢掉暴力分。然而我发现只需要取个模就可以了,考场上傻了。
学完莫队算法之后,发现这道题其实就是一个裸题。
一开始依然是莫队算法的方式,按左端点所在块的编号为第一关键字,右端点编号为第二关键字排序,
考虑先暴力处理每个块的第一组询问,之后可以发现我们只需要微调一下区间的左右端点就可以了。比如说:我上次处理了1 5,那么1 6就可以只把6加进去就可以了;如果这一次是2 6,那么我还需要把1给去掉。
考虑怎么转移:先离散化一下余数,记录[l, r]中这个数出现了几次,区间长度±1时显然答案改变值为这个点的余数的原出现次数(假设第一个数余数为2,用cnt[2]表示余数为2的数在当前区间的出现次数,那么去掉1之后答案改变值为cnt[2],自己yy一下应该想得通的)。
然后好像很有道理了,AC了?!好吧,其实是善良的出题人没有卡我们,其实p = 2 或 p = 5的情况是可以被卡掉的
特判一下就好了,两个数组分别表示[1, i]中2或5的倍数时有多少种情况及有多少个数末尾是2或5的倍数,用前缀和维护。
这样就可以完美AC了,可以过掉BZOJ上的新增数据了
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> #include<map> #include<vector> using namespace std; typedef long long LL; const int MAXN = 100011; const int MAXM = 100011; int p,m; int n; char ch[MAXN]; LL ans[MAXN]; LL mi[MAXN]; int size; int belong[MAXN]; LL hou[MAXN]; LL cnt[MAXN] LL c[MAXN]; int tot;//È¥ÖغóµÄ³¤¶È LL now; LL jisuan1[MAXN],jisuan2[MAXN]; struct wen{ int l,r,jilu; int k; }Q[MAXM]; inline int getint(){ char c=getchar();int w=0,q=0; while( (c<‘0‘ || c>‘9‘) && c!=‘-‘ ) c=getchar(); if(c==‘-‘) c=getchar(),q=1; while(c<=‘9‘ && c>=‘0‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w; } bool cmp(wen q,wen qq){ if(q.k==qq.k) return q.r<qq.r; return q.k<qq.k; } inline void init(){ mi[n]=1; for(int i=n-1;i>=1;i--) mi[i]=mi[i+1]*10%p; size=sqrt(n); if(n!=size*size) size++; hou[n+1]=0; for(int i=n;i>=1;i--) { belong[i]=(i-1)/size+1; hou[i]=hou[i+1]+(ch[i]-‘0‘)*mi[i]; hou[i]%=p; } memcpy(c,hou,sizeof(hou)); sort(c+1,c+n+1+1); tot=unique(c+1,c+n+1+1)-c-1; for(int i=1;i<=n+1;i++) hou[i]=lower_bound(c+1,c+n+1+1,hou[i])-c; m=getint(); for(int i=1;i<=m;i++) { Q[i].l=getint(),Q[i].r=getint(),Q[i].k=belong[Q[i].l],Q[i].jilu=i; Q[i].r++;//×¢Òâ¼ÓÒ» } } inline void update(int x,int type){ now-=cnt[hou[x]]*(cnt[hou[x]]-1)/2; cnt[hou[x]]+=type; now+=cnt[hou[x]]*(cnt[hou[x]]-1)/2; } inline void work(){ int l=1,r=0; sort(Q+1,Q+m+1,cmp); for(int i=1;i<=m;i++) { for(;r<Q[i].r;r++) update(r+1,1); for(;r>Q[i].r;r--) update(r,-1); for(;l<Q[i].l;l++) update(l,-1); for(;l>Q[i].l;l--) update(l-1,1); ans[Q[i].jilu]=now; } for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); } inline void solve(){//¼ÇÒ»ÏÂǰ׺ºÍ m=getint(); for(int i=1;i<=n;i++) { jisuan1[i]=jisuan1[i-1]; jisuan2[i]=jisuan2[i-1]; if( (ch[i]-‘0‘)%p==0 ) { jisuan1[i]++; jisuan2[i]+=i; } //jisuan1[i]=jisuan1[i-1]+((ch[i]-‘0‘)%p==0),jisuan2[i]=jisuan2[i-1]+ ( ( (ch[i]-‘0‘)%p==0 )?i:0 ); } for(int i=1;i<=m;i++) { int x=getint(),y=getint(); printf("%lld\n",jisuan2[y]-jisuan2[x-1] - (x-1)*(jisuan1[y]-jisuan1[x-1])); } } int main() { // freopen("number.in","r",stdin); // freopen("number.out","w",stdout); p=getint(); scanf("%s",ch+1); n=strlen(ch+1); //scanf("%s",ch); n=strlen(ch); //for(int i=n;i>=1;i--) ch[i]=ch[i-1]; if(p!=2 && p!=5) { init(); work(); } else solve(); return 0; }
标签:
原文地址:http://www.cnblogs.com/ljh2000-jump/p/5451448.html