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