11.02T4 贪心+线段树+后缀和

2封印一击3765

(hit.cpp/pas)

【问题描述】

  Nescafe由n种元素组成(编号为1~n),第i种元素有一个封印区间[ai,bi]。当封印力度E小于ai时,该元素将获得 ai的封印能量;当封印力度E在ai到bi之间时,该元素将获得E 的封印能量;而当封印力度E大于 bi 时,该元素将被破坏从而不能获得任何封印能量。现在圣主 applepi 想选择恰当的E,使得封印获得的总能量尽可能高。为了封印的最后一击尽量完美,就请你写个程序帮他计算一下吧!

【输入】

 第一行一个整数N。 
 接下来N行每行两个整数ai、bi,第 i+1行表示第 i种元素的封印区间。

【输出】

  两个用空格隔开的整数,第一个数是能够获得最多总能量的封印力度E,第二个数是获得的总能量大小。当存在多个E 能够获得最多总能量时,输出最小的E。

【输入样例】

2

5 10

20 25

【输出样例】

10 30

【数据范围与约定】 
  对于50%的数据,1<=N<=1000,1<=ai<=bi<=10000。 
  对于100%的数据,1<=N<=10^5,1<=ai<=bi<=10^9。

【分析】嵌套区间扫描计数(差分/线段树)

  简述:给你n个区间,你选择一个数,可以相应获得每个区间内的值,求使这个值最大的数及获得的最大值

思路:可以证明最优的数一定是区间的右端点,所以只要排个序,想办法处理这个和就行了。

将每个区间表示为两点,左记-1,右记1,排序统计该数属于几个区间,再加上所有左端点的的后缀和即可。统计点属于几个区间,差分最好,也可用线段树。

 

 

code:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #define N 600005
  5 #define lc (p<<1)
  6 #define rc (p<<1|1)
  7 using namespace std;
  8 struct node{
  9     long long l,r,yuanl,yuanr;
 10 }e[N];
 11 bool cmp(const node&a,const node&b){
 12     return a.l<b.l;
 13 }
 14 struct T{
 15     long long l,r,sum,lazy;
 16 }t[N];
 17 long long d[N],cnt,Temp[N],sum[N],temp[N];
 18 void pushup(long long p){
 19     t[p].sum=t[lc].sum+t[rc].sum;
 20 }
 21 void pushnow(long long p,long long v){
 22     t[p].sum+=(t[p].r-t[p].l+1)*v;
 23     t[p].lazy+=v;
 24 }
 25 void pushdown(long long p){
 26     if(t[p].lazy){
 27         pushnow(lc,t[p].lazy);
 28         pushnow(rc,t[p].lazy);
 29         t[p].lazy=0;
 30     }
 31 }
 32 void build(long long p,long long l,long long r){
 33     t[p].l=l,t[p].r=r;
 34     if(l==r){
 35         t[p].sum=0;
 36         return;
 37     }
 38     long long mid=l+r>>1;
 39     build(lc,l,mid);
 40     build(rc,mid+1,r);
 41     pushup(p);
 42 }
 43 void update(long long p,long long ql,long long qr,long long v){
 44     if(ql<=t[p].l&&t[p].r<=qr){
 45         pushnow(p,v);
 46         return;
 47     }
 48     pushdown(p);
 49     long long mid=t[p].l+t[p].r>>1;
 50     if(ql<=mid)update(lc,ql,qr,v);
 51     if(qr>mid)update(rc,ql,qr,v);
 52     pushup(p);
 53 }
 54 long long query(long long p,long long ql,long long qr){
 55     if(ql<=t[p].l&&t[p].r<=qr){
 56         return t[p].sum;
 57     }
 58     pushdown(p);
 59     long long mid=t[p].l+t[p].r>>1;
 60     long long ans=0;
 61     if(ql<=mid)ans+=query(lc,ql,qr);
 62     if(qr>mid)ans+=query(rc,ql,qr);
 63     pushup(p);
 64     return ans;
 65 }
 66 int main(){
 67     long long n;
 68     cin>>n;
 69     for(long long i=1;i<=n;i++){
 70         cin>>e[i].l>>e[i].r;
 71         e[i].yuanl=e[i].l;
 72         e[i].yuanr=e[i].r;
 73         d[++cnt]=e[i].l;
 74         d[++cnt]=e[i].r;
 75     }
 76     sort(d+1,d+cnt+1);
 77     cnt=unique(d+1,d+cnt+1)-d-1;
 78     build(1,1,cnt);
 79     for(long long i=1;i<=n;i++){
 80         e[i].l=lower_bound(d+1,d+cnt+1,e[i].l)-d;
 81         e[i].r=lower_bound(d+1,d+cnt+1,e[i].r)-d;
 82         update(1,e[i].l,e[i].r,1);
 83     }
 84     sort(e+1,e+n+1,cmp);
 85     for(long long i=1;i<=n;i++)Temp[i]=e[i].yuanl,temp[i]=e[i].l;
 86     for(long long i=n;i>=1;i--){
 87         sum[i]=sum[i+1]+Temp[i];
 88     }
 89     long long ans=0,ID=0;
 90     for(long long i=1;i<=n;i++){
 91         long long Ans=0;
 92         long long pos=upper_bound(temp+1,temp+n+1,e[i].r)-temp;
 93         Ans+=sum[pos];
 94         Ans+=query(1,e[i].r,e[i].r)*e[i].yuanr;
 95         if(Ans>ans){
 96             ID=e[i].yuanr;
 97             ans=Ans;
 98         }
 99         else if(Ans==ans)ID=min(ID,e[i].yuanr);
100     }
101     cout<<ID<<" "<<ans;
102     return 0;
103 }

over

posted @ 2018-11-03 21:17  saionjisekai  阅读(148)  评论(0编辑  收藏  举报