[BZOJ4542] [JZYZOJ2014][Hnoi2016] 大数(莫队+离散化)

正经题解在最下面

写的时候看了大神的题解[就是上面那个网址],看到下面这段话


观察题目,发现一串数s(l~r)整除p满足s(l~n-1)%p==s(r+1~n-1)%p 
但p值为2或5不满足这个性质需要特判(不过数据中好像没有,于是笔者没写,有兴趣的可以自己去写写。。。。。。)

然后问题转化为求一段区间中有几对相等的f值。

看到这里,我感觉豁然开朗,完全忽视了离散化的要求,我以为把余数值存起来扫一遍就行了离散个p啊..

写着写着完全参透这道题之后发现离散化的是余数啊,你不离散化怎么存数量啊,不存某个余数数量硬扫肯定超时啊....

然后我暴力硬扫果然[dian]超时了.........

[BZOJ4542] [JZYZOJ2014][Hnoi2016] 大数(莫队+离散化) - 拟南芥 - 鲸头鹳

 然后老老实实写离散化..........

 最重要的:2和5要特判
 
更重要的:离散化的时候要注意判定0的情况...即等于0时特判,不等0时离散化的赋值不应该从0开始,看加注释的那一段即可,不然会像我一样不停错两个点.....
我的程序200+大牛程序100-行..被吊着打.......我觉得我写的还挺清晰的...虽然完全不简洁
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<cstdio>
  5 #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 }
View Code

 

posted @ 2017-11-04 16:49  鲸头鹳  阅读(174)  评论(0编辑  收藏  举报