1 条题解
-
0Guest LV 0 MOD
-
1
记 \((l,r)\) 为一个序列内以 \(l\) 为起点的最短合法区间,如果有 \(r\) 随 \(l\) 的增大而增大的话,我们就可以使用尺取法。具体的做法就是不断的枚举 \(l\),同时求出 \(r\)。因为 \(r\) 随 \(l\) 增大而增大,所以 \(r\) 只有 \(n\) 次变化的机会,所以时间复杂度为\(\Theta(n) \)。
#include <cstdio> #include <algorithm> using namespace std; const int N=400005; struct Circle{ int loc, val;//分别表示位置locate和value }cr[N], qe[N]; bool cmp(Circle p, Circle q){ return p.loc < q.loc; } void in(int &x){ char c=getchar(); while (c<'0' || c>'9') c=getchar(); for (x=0; c>='0' && c<='9'; c=getchar()) x=x*10+c-'0'; } int main(){ freopen("gem.in", "r", stdin); freopen("gem.out", "w", stdout); int t; scanf("%d", &t); while (t--){ int n, l, k; scanf("%d %d %d", &n, &l, &k); for (int i=0; i<n; i++){ in(cr[i].loc); //scanf("%d", &cr[i].loc); cr[n+i].loc=cr[i].loc+l;//把环拉直,加倍延长处理 } for (int i=0; i<n; i++){ in(cr[i].val); //scanf("%d", &cr[i].val); cr[n+i].val=cr[i].val; } sort(cr, cr+2*n, cmp); int front=0, rear=0;//以队列的形式贪心求解(尺取法) qe[rear].loc=cr[0].loc; qe[rear].val=cr[0].val; rear++; int ans=cr[0].val, sum=cr[0].val; for (int i=1; i<2*n; i++){ while (front<rear && cr[i].loc-qe[front].loc>k) sum-=qe[front++].val; //保证在队列内部,loc之差小于k qe[rear].loc=cr[i].loc; qe[rear].val=cr[i].val; rear++; if (i!=n+front) sum+=cr[i].val; if (ans<sum) ans=sum; //printf("%d:%d:%d:%d:%d:%d\n",i,front,rear,cr[i].loc,sum,maxs); } printf("%d\n", ans); } return 0; }
- 1
信息
- ID
- 1423
- 难度
- 6
- 分类
- (无)
- 标签
- 递交数
- 34
- 已通过
- 3
- 通过率
- 9%
- 上传者