标签:open opp ppi 一半 build clu highlight find 题意
题意:n个数,m次询问,每次给你一个询问v,l,r,问你v%a[l]%a[l+1]%...%a[r]是多少。
a%b,结果要么不变,要么至少缩小到a的一半,于是用线段树,每次询问当前区间最靠左侧的小于等于当前数的值是多少,只需不超过log次询问就能使该数模完,就行了。
O(n(logn)^2)。
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; int n,m; ll minv[800005],a[200005]; void buildtree(int rt,int l,int r){ if(l==r){ scanf("%I64d",&minv[rt]); a[l]=minv[rt]; return; } int m=(l+r>>1); buildtree(rt<<1,l,m); buildtree(rt<<1|1,m+1,r); minv[rt]=min(minv[rt<<1],minv[rt<<1|1]); } int pos; int find(ll v,int rt,int l,int r){ if(l==r){ return l; } int m=(l+r>>1); if(minv[rt<<1]<=v){ return find(v,rt<<1,l,m); } else{ return find(v,rt<<1|1,m+1,r); } } bool query(int ql,int qr,ll v,int rt,int l,int r){ if(ql<=l && r<=qr){ if(minv[rt]<=v){ pos=find(v,rt,l,r); return 1; } return 0; } int m=(l+r>>1); if(ql<=m){ if(query(ql,qr,v,rt<<1,l,m)){ return 1; } } if(m<qr){ if(query(ql,qr,v,rt<<1|1,m+1,r)){ return 1; } } return 0; } int main(){ // freopen("j.in","r",stdin); ll z; int x,y; scanf("%d%d",&n,&m); buildtree(1,1,n); for(int i=1;i<=m;++i){ scanf("%I64d%d%d",&z,&x,&y); while(x<=y && query(x,y,z,1,1,n)){ z%=a[pos]; x=pos+1; } printf("%I64d\n",z); } return 0; }
标签:open opp ppi 一半 build clu highlight find 题意
原文地址:http://www.cnblogs.com/autsky-jadek/p/7634873.html