A题大意,不得不说当时后台数据多水(被人hack)。
从大到小遍历,不断累加上面的值,如果值变小了,就退出。
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<algorithm> using namespace std; const int N = 30; #define LL long long struct ZF { int a,s; } zf[N]; bool cmp(ZF A,ZF B) { return A.a > B.a; } int main() { int T,n,x,y; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d%d",&x,&y); zf[i].a = x; zf[i].s = y; } sort(zf,zf+n,cmp); LL Max = 0,k=1,tmp,sum=0,cnt=0; for(int i=0; i<n; i++) { for(int j=0; j<zf[i].s; j++) { sum += cnt+zf[i].a; cnt += zf[i].a; // printf("sum = %lld\n",sum); if(sum > Max) { Max=sum; } } } printf("%I64d\n",Max); } return 0; }
B题做出来没时间了,但是当时用了map,导致后来第一次交也超时,去掉后1800MS多AC,离散化1200MS多AC
这种枚举+二分的做法
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<algorithm> using namespace std; #define LL long long const int N = 50005; int d[4*N],n; struct Edge { int l,r; LL a,b,c; void Set(int ll,int rr,LL aa,LL bb,LL cc) { l = ll; r = rr; a = aa; b = bb; c = cc; } }; Edge ls[N],rs[N]; LL sumla[N],sumlb[N],sumlc[N]; LL sumra[N],sumrb[N],sumrc[N]; bool cmp1(Edge A,Edge B) { return A.l < B.l; } bool cmp2(Edge A,Edge B) { return A.r < B.r; } void getSumLR() { sort(ls+1,ls+n+1,cmp1); sumla[0] = sumlb[0] = sumlc[0] = 0; for(int i=1; i <= n; i++) { sumla[i] = sumla[i-1]+ls[i].a; sumlb[i] = sumlb[i-1]+ls[i].b; sumlc[i] = sumlc[i-1]+ls[i].c; } sort(rs+1,rs+n+1,cmp2); sumra[0] = sumrb[0] = sumra[0] = 0; for(int i=1; i <= n; i++) { sumra[i] = sumra[i-1]+rs[i].a; sumrb[i] = sumrb[i-1]+rs[i].b; sumrc[i] = sumrc[i-1]+rs[i].c; } } LL getAns(double x) { int l=1,r=n,mid,EndL=-1; while(l <= r) { mid = (l+r)>>1; if(ls[mid].l > x) { EndL = mid; r = mid-1; } else { l = mid+1; } } LL res = sumla[n]; if(EndL != -1) { res -= sumla[n]-sumla[EndL-1]; res += sumlc[n]-sumlc[EndL-1]; } l=1; r=n; int EndR=-1; while(l <= r) { mid = (l+r)>>1; if(rs[mid].r < x) { l = mid+1; EndR = mid; } else { r = mid-1; } } if(EndR != -1) { res -= sumra[EndR]; res += sumrb[EndR]; } return res; } int main() { // freopen("in.cpp","r",stdin); int T,l,r,cnt; LL a,b,c,ans; scanf("%d",&T); while(T--) { cnt=1; scanf("%d",&n); d[0] = 0; for(int i=1; i<=n; i++) { scanf("%d %d %I64d %I64d %I64d",&l,&r,&a,&b,&c); ls[i].Set(l,r,a,b,c); rs[i].Set(l,r,a,b,c); d[cnt++] = l; d[cnt++] = r; } getSumLR(); ans = 0; for(int i=0; i<cnt; i++) { ans = max(ans,getAns(d[i])); ans = max(ans,getAns(d[i]+0.5)); } printf("%I64d\n",ans); } return 0; }
比离散化的方法是要蠢很多的。
但是有个地方需要注意,遍历答案的时候,相同的温度需要一起加上,当时忘了。
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<algorithm> using namespace std; #define LL long long const int N = 50005*3; struct Array { LL val,tim; }a[N]; bool cmp(Array A,Array B) { return A.tim < B.tim; } int main() { // freopen("in.cpp","r",stdin); int T,cnt,n; LL l,r,aa,b,c,ans,sum; scanf("%d",&T); while(T--) { cnt = sum = 0; scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%I64d %I64d %I64d %I64d %I64d",&l,&r,&aa,&b,&c); a[cnt].val = -c+aa; a[cnt++].tim = 2*l; a[cnt].val = -aa+b; a[cnt++].tim = 2*r+1; sum += c; } sort(a,a+cnt,cmp); ans = sum; for(int i=0; i<cnt; i++) { for(int j=i; j<cnt; j++) { if(a[i].tim == a[j].tim) sum += a[j].val; else { i = j-1; break; } } ans = max(ans,sum); } printf("%I64d\n",ans); } return 0; }