标签:print return std efi cin 遍历 scan 接下来 while
给出一系列商品的价格,下面再给出q个人浏览商品的起点到末尾,和他带上的钱,如果看到能买的商品就买最多个,输出每个人浏览后所剩余的钱
如果对于每个人都遍历一遍的话,最坏的情况超过了1e9。
由于是取模运算,可以找到这个数列的第一个比他小的数,模它,比它大则无视。一个数最多模lgn下。
接下来最重要的是找到第一个比V小的数的位置
用倍增的方法存储一段数的最小值。
然后再以lgn的速度求出从a开始,比v小的第一个数。
#include <bits/stdc++.h> using namespace std; const int maxn=200000+10; #define LL long long LL num[maxn]; LL Min[maxn][25];//Min[i][j]从第i个元素到i+2ej-1个元素的最小值 int fin(LL V,int s) { for(int i=20;i>=1;i--) { while(Min[s][i]<=V&&Min[s][i-1]>V) { s+=(1<<(i-1)); } } if(num[s]<=V) return s; else return maxn; } int main() { int n,q,s,o; LL V; cin>>n>>q; for(int i=1;i<=n;i++) { scanf("%I64d",&num[i]); Min[i][0]=num[i]; } for(int j=1;j<=20;j++)//建立倍增数组 for(int i=1;i<=n;i++) { if(i+(1<<(j-1))<=n) Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]); else Min[i][j]=Min[i][j-1]; } for(int i=1;i<=q;i++) { scanf("%I64d %d %d",&V,&s,&o); int k=fin(V,s); while(k<=o) { V%=num[k]; k=fin(V,k+1); } printf("%I64d\n",V); } return 0; }
标签:print return std efi cin 遍历 scan 接下来 while
原文地址:https://www.cnblogs.com/carcar/p/8918767.html