免费送气球(权值线段树)

免费送气球
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 607    Accepted Submission(s): 141

 
Problem Description

又到了GDUT一年一度的程序设计竞赛校赛的时间啦。同学们只要参加校赛,并且每解出一道题目就可以免费获得由ACM协会和集训队送出的气球一个。听到这个消息,JMC也想参加免费拿气球。可是,由于JMC太菜了而被禁止参赛,于是他找到你想让你帮忙参加比赛,可以通过执行下面的C++程序解决问题后获得气球并送给他。JMC保证了下面的程序一定能获得正确的结果。

void solve(int Q, int type[], long long first[], long long second[]) {
    vector<long long> vec;
    for (int i = 0; i < Q; ++i) {
        if (type[i] == 1) {
            long long k = first[i], val = second[i];
            while (k--) {
                vec.push_back(val);
            }
        }
        else if (type[i] == 2) {
            sort(vec.begin(), vec.end());
            long long l = first[i] - 1, r = second[i], res = 0;
            while (l < r) {
                res = (res + vec[l++]) % 1000000007;
            }
            printf("%lld\n", res);
        }
    }
}


为防止你被JMC的代码搞到头晕目眩,JMC特意给出了问题的文字描述。已知一开始有一个空序列,接下来有Q次操作,每次操作给出type、first和second三个值。当type为1时,意味着该操作属于第一种操作:往序列尾部添加first个second数。当type为2时,意味着该操作属于第二种操作:查询序列中第first小至第second小的数值之和(一共有(second - first + 1)个数被累加),并将结果对1000000007取模后输出。

 
Input

单组数据
第一行一个Q(1 <= Q <= 1e5),代表Q次操作。
接下来有Q行,每行包含三个整数type、first和second;其中1 <= type <= 2。当type等于1时,0 <= first,second < 1e9。当type等于2时,1 <= first <= second,且first和second均不大于目前已添加进序列的数的数量。

 
Output

对于每次操作二,将结果对1000000007取模后输出。

 
Sample Input


 
6 1 5 1 1 6 3 2 2 5 2 4 8 1 2 2 2 4 8

 
Sample Output


 
4 11 9

 
Source

“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛

 
Recommend

liuyiding

这个题一看求第first小就想到了主席树。

但是由于只在所有序列查找,就没必要写主席树了,太复杂了,写一个权值线段树就可以了。

但是这题有几个部分没太看懂,当时就没写出来。

1、加在序列的最后部分,这句被看蒙了,其实不用管,离散后就按照位置插入就可以了。

2、第first小,如果一个数相同的有很多个算不算同一个小呢?答案是NO。

AC代码:
 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
const ll mod=1000000007;
int n,tot;
struct node
{
	int ty;
	ll l,r;
}a[N];
ll sum[N*4],num[N*4],b[N];
void pushup(int id)
{
	sum[id]=(sum[id<<1]+sum[id<<1|1])%mod;
	num[id]=num[id<<1]+num[id<<1|1];
}

void update(int id,int l,int r,int pos,ll t)
{
	if(l==r)
	{
		num[id]+=t;
		sum[id]+=(b[pos]*t)%mod;
		sum[id]%=mod;
		return ;
	}
	int mid=l+r>>1;
	if(pos<=mid) 
	update(id<<1,l,mid,pos,t);
	else update(id<<1|1,mid+1,r,pos,t);
	pushup(id);
}

ll query(int id,int l,int r,ll k)
{
	if(k==0) return 0;
	if(l==r)
	return 1ll*k*b[l]%mod;
	ll ans=0;
	int mid=l+r>>1;
	if(num[id<<1]>k) 
	ans=query(id<<1,l,mid,k)%mod;
	else
	ans=(sum[id<<1]+query(id<<1|1,mid+1,r,k-num[id<<1]))%mod;
	return ans%mod;
}
int main()
{
	cin>>n;
	tot=0;
	for(int i=1;i<=n;i++) 
	{
		scanf("%d%lld%lld",&a[i].ty,&a[i].l,&a[i].r);
		if(a[i].ty==1) b[++tot]=a[i].r;
	}
	sort(b+1,b+1+tot);
	tot=unique(b+1,b+1+tot)-b-1;
	for(int i=1;i<=n;i++)
	{
		if(a[i].ty==1){
			int id=lower_bound(b+1,b+1+tot,a[i].r)-b;
			update(1,1,tot,id,a[i].l);
		}
		else
		{
			if(a[i].ty==1) printf("%lld\n",query(1,1,tot,a[i].r)%mod);
			else
			printf("%lld\n",(query(1,1,tot,a[i].r)-query(1,1,tot,a[i].l-1)+mod)%mod);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/88978523