bzoj2506 离线操作
2015-07-17 21:51
387 查看
~~~挺神奇的一道题!!!!!!!!
这道题满足区间减法,所以把一个区间【L,R】询问拆为【1,R】区间的答案减去【1,L-1】区间的答案。
将p分为两类,一类为p<=100,另一类p>100;
当p<=100时,开一个数组F[P][K],遍历到当前点i,暴力枚举P,更新F[P][K],并找出询问区间【1,i】,更新它的答案。
当p>100时,符合条件的数最多有101个,所以也基本是暴力~~
开一个数组储存当前数出现了几次。遍历到前点i,更新数组,找出询问区间【1,i】,然后直接暴力查询k+n*p出现了多少次。
这道题满足区间减法,所以把一个区间【L,R】询问拆为【1,R】区间的答案减去【1,L-1】区间的答案。
将p分为两类,一类为p<=100,另一类p>100;
当p<=100时,开一个数组F[P][K],遍历到当前点i,暴力枚举P,更新F[P][K],并找出询问区间【1,i】,更新它的答案。
当p>100时,符合条件的数最多有101个,所以也基本是暴力~~
开一个数组储存当前数出现了几次。遍历到前点i,更新数组,找出询问区间【1,i】,然后直接暴力查询k+n*p出现了多少次。
#include <algorithm> #include <algorithm> #include <iostream> #include<string.h> #include <fstream> #include <math.h> #include <vector> #include <cstdio> #include <string> #include <queue> #include <stack> #include <map> #include <set> #define exp 1e-8 #define fi first #define se second #define ll long long #define INF 0x3f3f3f3f #define lson l,mid,rt<<1 #define pb(a) push_back(a) #define mp(a,b) make_pair(a,b) #define rson mid+1,r,(rt<<1)+1 #define all(a) a.begin(),a.end() #define mm(a,b) memset(a,b,sizeof(a)); #define for1(a,b) for(int a=1;a<=b;a++)//1---(b) #define rep(a,b,c) for(int a=b;a<=c;a++)//b---c #define repp(a,b,c)for(int a=b;a>=c;a--)/// using namespace std; void bug(string m="here"){cout<<m<<endl;} template<typename __ll> inline void READ(__ll &m){__ll x=0,f=1;char ch=getchar();while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}m=x*f;} template<typename __ll>inline void read(__ll &m){READ(m);} template<typename __ll>inline void read(__ll &m,__ll &a){READ(m);READ(a);} template<typename __ll>inline void read(__ll &m,__ll &a,__ll &b){READ(m);READ(a);READ(b);} template<typename __ll>inline void read(__ll &m,__ll &a,__ll &b,__ll &c){READ(m);READ(a);READ(b);READ(c);} template < class T > T gcd(T a, T b) { return b ? gcd(b, a % b) : a; } template < class T > T lcm(T a, T b) { return a / gcd(a, b) * b; } template < class T > inline void rmin(T &a, const T &b) { if(a > b) a = b; } template < class T > inline void rmax(T &a, const T &b) { if(a < b) a = b; } template < class T > T pow(T a, T b) { T r = 1; while(b > 0) { if(b & 1) r = r * a; a = a * a; b /= 2; } return r; } template < class T > T pow(T a, T b, T mod) { T r = 1; while(b > 0) { if(b & 1) r = r * a % mod; a = a * a % mod; b /= 2; } return r; } const int maxn=100000+100; struct dat { int x,p,k,flag,idx; dat(){} dat(int xx,int pp,int kk,int flagflag,int idxidx) {x=xx,p=pp,k=kk,flag=flagflag,idx=idxidx;} }small[maxn*2],big[maxn*2]; int cnt_s=0,cnt_b=0; int f[110][110]; int cnt[maxn]; int num[maxn]; int ans[maxn]; int n,m; bool cmp(dat a,dat b){return a.x<b.x;} //a.x<=b.x wa~~~我也是醉了 void solve_small() { sort(small,small+cnt_s,cmp); int k=0; while(k<cnt_s&&small[k].x==0)k++; //剔除区间【1,0】 for1(i,n) { for1(j,100)f[j][num[i]%j]++; //更新 while(k<cnt_s&&small[k].x==i) //找出符合的区间 ans[small[k].idx]+=small[k].flag*f[small[k].p][small[k].k],k++; } } void solve_big() { sort(big,big+cnt_b,cmp); int k=0; while(k<cnt_b&&big[k].x==0)k++;//剔除区间【1,0】 for1(i,n) { cnt[num[i]]++; //更新 while(k<cnt_b&&big[k].x==i)//找出符合的区 { for(int j=big[k].k;j<=10000;j+=big[k].p) ans[big[k].idx]+=big[k].flag*cnt[j]; k++; } } } int main() { read(n,m); for1(i,n)read(num[i]); for1(i,m) { int l,r,p,k; read(l,r,p,k); if(p<=100) small[cnt_s++]=dat(l-1,p,k,-1,i),small[cnt_s++]=dat(r,p,k,1,i); else big[cnt_b++]=dat(l-1,p,k,-1,i),big[cnt_b++]=dat(r,p,k,1,i); } solve_small(); solve_big(); for1(i,m)printf("%d\n",ans[i]); }
相关文章推荐
- 社会现象——我喜欢这个世界。
- scrollTop是什么及用法说明
- 最长公共子序列(LCS)
- MapKit的使用显示当前位置
- 动态规划专题学习之一-概述分析
- 一次只有过程没有结果的努力
- HDU 4862 Jump(最大k路径覆盖 费用流)
- UML类图几种关系的总结
- linux系统网络命令(五)
- scala中神奇的map tuple zip
- iOS第二天注意和学习重点
- Hive数据加载(内部表,外部表,分区表)
- 支撑统计学的七大支柱!
- 喵哈哈的日常选数问题(数位DP)
- 关于Service中bindService注意的几个问题
- 1046. Shortest Distance (20) 坑我
- 关于Service中bindService注意的几个问题
- Tortoise SVN 提示 clean up 然而 clean up 没卵用的解决方法
- 线段树区间修改 懒惰标记 维护和、最大值、最小值
- LINUX之文件解压与压缩汇总