zoukankan      html  css  js  c++  java
  • HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464

    免费送气球

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


    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 ", 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

    解题思路:

    理解学习一波主席树:https://blog.csdn.net/g21wcr/article/details/82970228

    1操作正常建权值线段树,查询操作则是利用 前缀和作差的方法来求区间和。

    AC code:

     1 #include <bits/stdc++.h>
     2 #define LL long long
     3 using namespace std;
     4 const LL INF = 0x3f3f3f3f;
     5 const LL MOD = 1e9+7;
     6 const int MAXN = 1e5+10;
     7 
     8 LL sum[MAXN*40], val[MAXN*40];
     9 int ls[MAXN*40], rs[MAXN*40];
    10 int cnt;
    11 
    12 void update(int &Root, int L, int R, LL k, LL num)
    13 {
    14     if(!Root) Root = ++cnt;
    15     sum[Root]+=k;
    16     val[Root]+=(LL)k*num;
    17     val[Root]%=MOD;
    18     if(L == R) return;
    19     int mid = (L+R)>>1;
    20     if(num <= mid) update(ls[Root], L, mid, k, num);
    21     else update(rs[Root], mid+1, R, k, num);
    22 }
    23 
    24 LL query(int Root, int L, int R, LL k)                  //前 k 小的值的和
    25 {
    26     if(L == R) return 1LL*k*L%MOD;
    27     int mid = (L+R)>>1;
    28     LL ans = 0;
    29     if(k > sum[ls[Root]])
    30         ans = (val[ls[Root]] + query(rs[Root], mid+1, R, k-sum[ls[Root]]))%MOD;
    31     else
    32         ans = query(ls[Root], L, mid, k);
    33 
    34     return ans%MOD;
    35 }
    36 
    37 int main()
    38 {
    39     int Q_case, rt = 0;
    40     scanf("%d", &Q_case);
    41     while(Q_case--){
    42         int op;
    43         LL L, R;
    44         scanf("%d %lld %lld", &op, &L, &R);
    45         if(op == 1) update(rt, 0, 1e9, L, R);
    46         else{
    47             LL ans = (query(rt, 0, 1e9, R) - query(rt, 0, 1e9, L-1)%MOD + MOD)%MOD;     //类似于利用前缀和的差 来 求解区间的和
    48             printf("%lld
    ", ans);
    49         }
    50     }
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    android之自定义ViewGroup和自动换行的布局的实现
    早上开发有感:事情原本可以变的简单
    android中textview显示汉字,字母,数字乱行行问题解决
    MeasureSpec介绍及使用详解
    android中status bar 小结
    Android推送方式比较(转)
    error: Entry 'xxxxxx' not uptodate. Cannot merge.
    android2.3:加载你的SD卡与can't mount /dev/block/mmcblk0
    有客户自远方来,不亦乐乎?唉,怎一个愁字了得
    卸载Norton 8企业版的一次经历
  • 原文地址:https://www.cnblogs.com/ymzjj/p/10547836.html
Copyright © 2011-2022 走看看