您好,欢迎来到五一七教育网。
搜索
您的当前位置:首页[P40][JXOI2017]加法(贪心+树状数组+堆)

[P40][JXOI2017]加法(贪心+树状数组+堆)

来源:五一七教育网

不要相信数据范围,应该是$1\leq n,m \leq 10^5$。

二分答案,贪心扫一遍,对于小于二分值的位置,用堆找到包含它且向右延伸最长的区间加上它,区间加用差分树状数组实现。

 1 #include<cstdio>
 2 #include<queue>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=l; i<=r; i++)
 6 using namespace std;
 7 
 8 const int N=200100;
 9 priority_queue<int>Q;
10 int T,n,m,k,A,q[N],a[N],c[N],stk[N];
11 struct P{ int l,r; }p[N];
12 bool cmp(P a,P b){ return a.l<b.l; }
13 void add(int x,int k){ for (; x<=n+1; x+=x&-x) c[x]+=k; }
14 int que(int x){ int res=0; for (; x; x-=x&-x) res+=c[x]; return res; }
15 
16 bool chk(int lim){
17     while (!Q.empty()) Q.pop();
18     memset(c,0,sizeof(c)); int top=0,j=1,cnt=0;
19     rep(i,1,n) if (a[i]<lim) stk[++top]=i;
20     rep(i,1,top){
21         while (j<=m && p[j].l<=stk[i]) Q.push(p[j].r),j++;
22         while (a[stk[i]]+que(stk[i])<lim){
23             cnt++; if (cnt>k || Q.empty()) return 0;
24             int x=Q.top(); Q.pop(); add(stk[i],A); add(x+1,-A);
25         }
26     }
27     return 1;
28 }
29 
30 int main(){
31     freopen("P40.in","r",stdin);
32     freopen("P40.out","w",stdout);
33     for (scanf("%d",&T); T--; ){
34         scanf("%d%d%d%d",&n,&m,&k,&A);
35         rep(i,1,n) scanf("%d",&a[i]);
36         rep(i,1,m) scanf("%d%d",&p[i].l,&p[i].r);
37         sort(p+1,p+m+1,cmp);
38         int l=1,r=120000000,mid,ans;
39         while (l<=r){
40             mid=(l+r)>>1;
41             if (chk(mid)) ans=mid,l=mid+1; else r=mid-1;
42         }
43         printf("%d\n",ans);
44     }
45     return 0;
46 }

 

转载于:https://www.cnblogs.com/HocRiser/p/8806344.html

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 517ttc.cn 版权所有 赣ICP备2024042791号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务