2017 Multi-University Training Contest

来源:互联网 发布:c语言 纸牌 编辑:程序博客网 时间:2024/06/11 01:29

传送门
//题意还是稍微有点难懂, 就是在序列a后面再添n个元素, 但是每一个元素要满足题目所给的条件, 就是从b序列中任意抽出一个, 使得a序列中从b[k]下标到即将被添加的那个元素的下标中抽取一个max, 最后求出a(n+1)~a(n+n)的和mod, 注意每一个b[k]最多只能被用一次, 而且注意每一个b[i]的范围都是<=n的.

//思路: 为了max, 所以贪心的选择, 每一次我们都选可以选到的最大值, 并且新加进去的元素也可以使用, 所以我用的是一个优先队列去维护一个最大的val值.

//ps:mmp, 比赛的时候吧数据范围看错, 写的1e5, 一直T, T到想吐血. 后面才发现范围开小了, 开成5e5就过了…….

AC Code (483ms)

/** @Cain*/#define Fill(x,y) memset(x,y,sizeof(x))using namespace std;const int maxn=5e5+5;int a[maxn],b[maxn];struct node{    int id,val;    bool friend operator<(const node &x,const node &y){        return x.val<y.val;    }    node(int id=0,int val = 0):id(id),val(val){}};void solve(){    int n;    while(~scanf("%d",&n)){        priority_queue<node>q;        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);            q.push(node(i,a[i]-i));        }        for(int i=1;i<=n;i++)            scanf("%d",&b[i]);        sort(b+1,b+n+1);        ll res = 0; int r = 1;        int cnt = 1;        while(!q.empty()){            node t = q.top();            q.pop();            for(int i=r;i<=n;i++){                if(b[i]<=t.id){                    r = i+1;                    res += t.val;                    res %= mod;                    q.push(node(n+cnt,t.val-n-cnt));                    cnt++;                }                else break;            }            if(cnt > n) break;        }        printf("%lld\n",res);    }}