hdu6464 免费送气球 (线段树)

免费送气球

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 972    Accepted Submission(s): 45


 

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

解题思路:更新操作可以看作对一个点的更新,记录区间和和区间个数,然后查询的话二分就可以了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<map>
#include<algorithm>
using namespace std;
#define LL long long
#define sca(x) scanf("%d",&x)
#define lowb(x) (x&(-x))
#define pb(x) push_back(x)
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define pri(x) printf("%d\n",x);
#define N 200005
#define inf 0x3f3f3f3f
const LL mod=1000000007;


struct node
{
    LL op,l,r;
}a[N];
LL n;

vector<LL>V;
struct node1
{
    LL sz,sum;
}T[N*5];

void upd(int rt,int l,int r,LL pos,LL val)
{
    T[rt].sz+=val;
    T[rt].sum=(T[rt].sum+(val*V[pos-1])%mod)%mod;
    if(l==r)return ;
    int m=(l+r)>>1;
    if(pos<=m)upd(rt<<1,l,m,pos,val);
    else upd(rt<<1|1,m+1,r,pos,val);
}

LL query(LL p)
{
    int rt=1,l=1,r=n;
    LL ans=0;
    while(l!=r)
    {
        int m=(l+r)>>1;
        if(T[rt<<1].sz>=p)r=m,rt<<=1;
        else
        {
            l=m+1;
            ans=(ans+T[rt<<1].sum)%mod;
            p-=T[rt<<1].sz;
            rt=rt<<1|1;
        }
    }
    if(p!=0)ans=(ans+(p*V[l-1])%mod)%mod;
    return ans;
}

int main()
{
    int q;
    scanf("%d",&q);
    rep(i,1,q)
    {
        scanf("%lld%lld%lld",&a[i].op,&a[i].l,&a[i].r);
        V.pb(a[i].r);
    }
    sort(V.begin(),V.end());
    unique(V.begin(),V.end());
    n=V.size()+1;
    for(int i=1;i<=q;i++)
    {
        if(a[i].op==1)
        {
            int pos=lower_bound(V.begin(),V.end(),a[i].r)-V.begin()+1;
            upd(1,1,n,(LL)pos,(LL)a[i].l);
        }
        else
        {
            printf("%lld\n",((query(a[i].r)-query(a[i].l-1))+mod)%mod);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/88616762