ICPC Pacific Northwest Regional Contest 2016 - Shopping(线段树)

The sale bin of Big Box Bargains contains n products in a row. The ith item has price ai per unit.There is no limit to the quantity of any item. 

There are q customers who will enter the store to buy items. The ith customer has vi dollars, startsat item li and walks to the right to item ri (inclusive), one item at a time. 

Each time they encounter an item, they will buy as many units of the item as they can afford. 

You are now wondering, for each customer, how much money they will have left after buying items.

Input

The first line of input contains two space-separated integers n and q (1 ≤ n, q ≤ 200,000).The next line of input contains n space-separated integers ai (1 ≤ ai ≤ 10^18).Each of the next q lines contains three space-separated integers vi (1 ≤ vi ≤ 10^18), li, and ri(1 ≤ li ≤ ri ≤ n).

Output

For each of the q customers, print, on a single line, a single integer indicating the remaining amountof money after shopping.

样例输入复制

5 3
5 3 2 4 6
8 5 5
107 1 4
7 3 5

样例输出复制

2
0
1

题目链接:点击查看

题目大意:给出一个数列 a ,每次询问给出一个 x 和一段区间 [ l , r ] ,问 x % a[ l ] % a[ l + 1 ] % ... % a[ r ] 后的答案

题目分析:因为如果 x 对一个数取余想要有贡献的话,那么这个数必须严格小于 x ,同时,在取余后,x 最大会变为 x / 2 ,那么最多只需要经过 logx 次操作 x 就会变为 0 了,这样的话我们只需要用线段树,找出区间 [ l , r ] 内首个小于 x 的数,返回其位置,如此往复不断模拟即可,时间复杂度是 n logn logn 的

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<unordered_map>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=1e6+100;

vector<LL>node;

LL dp[N];

void discreate()
{
	sort(node.begin(),node.end());
	node.erase(unique(node.begin(),node.end()),node.end());
}

int get_id(LL x)
{
	return lower_bound(node.begin(),node.end(),x)-node.begin()+1;
}

struct Seg
{
	LL l,r;
	bool operator<(const Seg& t)const
	{
		if(l!=t.l)
			return l<t.l;
		return r<t.r;
	}
}a[N];

struct Node
{
	int l,r;
	LL mmax;
}tree[N<<2];

void pushup(int k)
{
	tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax);
}

void build(int k,int l,int r)
{
	tree[k].l=l;
	tree[k].r=r;
	tree[k].mmax=0;
	if(l==r)
		return;
	int mid=l+r>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}

void update(int k,int pos,LL val)
{
	if(tree[k].l==tree[k].r)
	{
		tree[k].mmax=max(val,tree[k].mmax);
		return;
	}
	int mid=tree[k].l+tree[k].r>>1;
	if(pos<=mid)
		update(k<<1,pos,val);
	else
		update(k<<1|1,pos,val);
	pushup(k);
}

LL query(int k,int l,int r)
{
	if(l>r)
		return 0;
	if(tree[k].r<l||tree[k].l>r)
		return 0;
	if(tree[k].l>=l&&tree[k].r<=r)
		return tree[k].mmax;
	return max(query(k<<1,l,r),query(k<<1|1,l,r));
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	LL n,m;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld",&a[i].l,&a[i].r);
		node.push_back(a[i].l-1);
		node.push_back(a[i].l);
		node.push_back(a[i].r);
	}
	discreate();
	build(1,1,node.size());
	sort(a+1,a+1+m);
	LL ans=0;
	for(int i=1;i<=m;i++)
	{
		LL l=a[i].l,r=a[i].r;
		LL mmax=query(1,1,get_id(a[i].l-1));
		dp[i]=mmax+r-l+1;
		update(1,get_id(a[i].r),dp[i]);
		ans=max(ans,dp[i]);
	}
	printf("%lld\n",n-ans);










    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106890804