[BZOJ4542] [JZYZOJ2014][Hnoi2016] 大數(莫隊+離散化)
阿新 • • 發佈:2017-11-04
離散 離散化 ios nod 技術 相等 work turn 需要 正經題解在最下面
http://blog.csdn.net/qq_32739495/article/details/51286548
寫的時候看了大神的題解[就是上面那個網址],看到下面這段話
觀察題目,發現一串數s(l~r)整除p滿足s(l~n-1)%p==s(r+1~n-1)%p
但p值為2或5不滿足這個性質需要特判(不過數據中好像沒有,於是筆者沒寫,有興趣的可以自己去寫寫。。。。。。)
然後問題轉化為求一段區間中有幾對相等的f值。
看到這裏,我感覺豁然開朗,完全忽視了離散化的要求,我以為把余數值存起來掃一遍就行了離散個p啊..
寫著寫著完全參透這道題之後發現離散化的是余數啊,你不離散化怎麽存數量啊,不存某個余數數量硬掃肯定超時 啊....
然後我暴力硬掃果然[dian]超時了.........
然後老老實實寫離散化..........
最重要的:2和5要特判 更重要的:離散化的時候要註意判定0的情況...即等於0時特判,不等0時離散化的賦值不應該從0開始,看加註釋的那一段即可,不然會像我一樣不停錯兩個點..... 我的程序200+大牛程序100-行..被吊著打.......我覺得我寫的還挺清晰的...雖然完全不簡潔1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdio> 5View Code#include<algorithm> 6 using namespace std; 7 int p,m,s=0,sz; 8 int a[100010]={}; 9 int bel[100010]={}; 10 int ans[100010]={}; 11 long long mo[100010]={}; 12 long long b[100010]={}; 13 long long re[10][100010]={}; 14 int vis[100010]={}; 15 int tot[10]={}; 16 struct nod{ 17 int x,y; 18 int id; 19 }e[100010]; 20 void readin(){ 21 char c=getchar(); 22 while(c<‘0‘||c>‘9‘){ 23 c=getchar(); 24 } 25 while(c>=‘0‘&&c<=‘9‘){ 26 a[++s]=(int)(c-‘0‘); 27 c=getchar(); 28 } 29 } 30 bool mmp(nod aa,nod bb){ 31 if(bel[aa.x]==bel[bb.x]){ 32 if(aa.y==bb.y){ 33 return aa.x<bb.x; 34 } 35 return aa.y<bb.y; 36 } 37 return bel[aa.x]<bel[bb.x]; 38 } 39 void work(){ 40 int l=1,r=0; 41 int an=0; 42 for(int i=1;i<=m;i++){ 43 while(l>e[i].x){ 44 l--; 45 an+=vis[mo[l]]; 46 if(mo[r+1]==mo[l]){ 47 an+=1; 48 } 49 vis[mo[l]]++; 50 } 51 while(r<e[i].y){ 52 r++; 53 vis[mo[r]]++; 54 an+=vis[mo[r+1]]; 55 } 56 while(l<e[i].x){ 57 vis[mo[l]]--; 58 an-=vis[mo[l]]; 59 if(mo[r+1]==mo[l]){ 60 an-=1; 61 } 62 l++; 63 } 64 while(r>e[i].y){ 65 an-=vis[mo[r+1]]; 66 vis[mo[r]]--; 67 r--; 68 } 69 ans[e[i].id]=an; 70 } 71 for(int i=1;i<=m;i++){ 72 printf("%d\n",ans[i]); 73 } 74 } 75 void work5(){ 76 int l=1,r=0; 77 int an=0; 78 for(int i=1;i<=m;i++){ 79 while(l>e[i].x){ 80 l--; 81 vis[a[l]%p]++; 82 an+=vis[0]; 83 } 84 while(r<e[i].y){ 85 r++; 86 vis[a[r]%p]++; 87 if(a[r]%p==0){ 88 an+=r-l+1; 89 } 90 } 91 while(l<e[i].x){ 92 an-=vis[0]; 93 vis[a[l%p]]--; 94 l++; 95 } 96 while(r>e[i].y){ 97 if(a[r]%p==0){ 98 an-=r-l+1; 99 } 100 vis[a[r]%p]--; 101 r--; 102 } 103 ans[e[i].id]=an; 104 } 105 for(int i=1;i<=m;i++){ 106 printf("%d\n",ans[i]); 107 } 108 } 109 int main(){ 110 //freopen("wtf.in","r",stdin); 111 scanf("%d",&p); 112 readin(); 113 sz=(int)sqrt((double)s); 114 scanf("%d",&m); 115 for(int i=1;i<=m;i++){ 116 scanf("%d%d",&e[i].x,&e[i].y); 117 if(e[i].x>=s){ 118 e[i].x=s; 119 } 120 if(e[i].y>s){ 121 e[i].y=s; 122 } 123 e[i].id=i; 124 } 125 for(int i=1;i<=s;i++){ 126 bel[i]=(i-1)/sz+1; 127 } 128 sort(e+1,e+1+m,mmp); 129 if(p==2||p==5){ 130 work5(); 131 return 0; 132 } 133 for(int i=0;i<=9;i++){ 134 re[i][1]=i%p; 135 tot[i]=1; 136 } 137 for(int i=s,w=1;i>=1;i--){ 138 int x=a[i]; 139 while(tot[x]<w){ 140 tot[x]++; 141 re[x][tot[x]]=re[x][tot[x]-1]*10%p; 142 } 143 mo[i]=(re[x][w]+mo[i+1])%p; 144 b[i]=mo[i]; 145 w++; 146 } 147 sort(b+1,b+1+s); 148 int size=unique(b+1,b+1+s)-b-1; 149 for(int i=1;i<=s;i++){//離散化部分....註意一定要特判.. 150 if(mo[i]==0){ 151 mo[i]==0; 152 } 153 else{ 154 mo[i]=lower_bound(b+1,b+1+s,mo[i])-b;//這裏-1且輸入字符串中沒有0時,1會被離散化為0 155 } 156 } 157 work(); 158 return 0; 159 }
[BZOJ4542] [JZYZOJ2014][Hnoi2016] 大數(莫隊+離散化)