https://vjudge.net/problem/HDU-6205
题意略
当时队友秒出的思路是,保存一个前缀和,然后枚举每一位 i,查找 i 到 i+n-1 qu第一区,第一个前缀和小于当前前缀和的数。
然后开始写,跟多校那个题思路写法都一样。
结果ME了
我 ???,队友???
然后改小数组 ME
我??? 队友???
然后手动加栈 ME
我??? 队友???
然后另外一个队友重写线段树 ME
我??? 队友1??? 队友2 ???
队友2疯狂认为是return inf 的问题,被我和队友1赶走。
放弃此题; to be continue...
最后半小时觉得再改改,改 ME
我 。。。 队友1 。。。
我换了思路,一想,发现对于 枚举每位 i ,找到它的可取区间的尾部 j 时,我们下次可以直接跳到尾部 j +1 开始为新的起点 i,因为从原位置 到尾部 i - j 这个区间都不会再有比原来值更优秀的解了。想到这不解释,直接写完交,还剩2min,wa了
我??。。。 队友12 (面无表情,习以为常);
后来发现,j的枚举范围错了,j应该枚举到 i + n -1 ,并且寻找尾部时,不一定是大于零,也有可能是i - j 长度为n取到整个区间。
改完,遂AC
L 题 end。。。
PS : 发现学弟学妹的H题过得那么多,过得我很懵,结果看了看他们的代码,被我hack掉了直接,,
原来不是我们太菜学弟学妹太强,而是数据太水。。。。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define lson root*2,l,mid
#define rson root*2+1,mid+1,r
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn=2e6+100;
int sum[maxn*2];
int a[maxn];
int b[maxn];
int ans[maxn*2];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]);
int N = 2*n;
sum[0] = 0;
ans[0] = 0;
for(int i=1; i<=n; i++)
{
sum[i] = sum[i-1] + a[i]-b[i];
ans[i] = ans[i-1] + a[i];
}
for(int i=1,j=n+1; i<=n;j++, i++)
{
sum[j] = sum[j-1] + a[i] - b[i];
ans[j] = ans[j-1] + a[i];
}
int t = 0;
long long res = 0;
int d = 0;
for(int i=1; i<=n; i++)
{
for(int j=i; j<=n+i-1; j++)
{
if( sum[j] - sum[i-1] < 0)
{
if(res < ans[j]-ans[i-1])
{
d = i-1;
res = ans[j]-ans[i-1];
}
i = j;
break;
}
if(j-i+1==n && res< ans[j]- ans[i-1])
{
d = i - 1;
res = ans[j]- ans[i-1];
break;
}
}
}
printf("%d\n",d);
}
return 0;
}
附上傻逼 的ME代码。说不准某天就知道为啥ME了呢
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define lson root*2,l,mid
#define rson root*2+1,mid+1,r
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn=1e6+5;
int sum[maxn*2];
int a[maxn];
int b[maxn];
int ans[maxn*2];
int mi[maxn*8];
void build(int root,int l,int r)
{
if(l==r)
{
mi[root] = sum[l];
return ;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
mi[root] = min(mi[root*2],mi[root*2+1]);
}
int dfs(int x,int l,int r,int rt)
{
if(l==r)
{
return l;
}
int mid=(l+r)>>1;
int zz=inf;
if(mi[rt<<1]<x) zz=dfs(x,l,mid,rt<<1);
else if(mi[rt<<1|1]<x) zz=dfs(x,mid+1,r,rt<<1|1);
return zz;
}
int query(int x,int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
if(mi[rt]<x)
{
return dfs(x,l,r,rt);
}
else return inf;
}
int mid=(l+r)>>1;
int mini=inf;
if(mi[rt*2]<x && L<=mid) mini=min(mini,query(x,L,R,l,mid,rt<<1));
if(mini!=inf) return mini;
if(mi[rt*2+1]<x && R>mid) mini=min(mini,query(x,L,R,mid+1,r,rt<<1|1));
return mini;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]);
int N = 2*n;
sum[0] = 0;
ans[0] = 0;
for(int i=1; i<=n; i++)
{
sum[i] = sum[i-1] + a[i]-b[i];
ans[i] = ans[i-1] + a[i];
}
for(int i=1,j=n+1; i<=n;j++, i++)
{
sum[j] = sum[j-1] + a[i]-b[i];
ans[j] = ans[j-1] + a[i];
}
build(1,1,N);
int res = 0;
int dong = n;
for(int i=1; i<=n; i++)
{
int cnt = sum[i] - sum[i-1];
int t ;
if(sum[i-1]==mi[1])
t = i+n-1;
else if(sum[i]-sum[i-1]<0)
t = i;
else
t = query(sum[i-1],i,i+n-1,1,N,1);
if(t==inf)
{
t = i+n-1;
}
if(t>maxn)
{
t = i+n-1;
}
if(ans[t]-ans[i-1]>res)
{
dong =i-1;
res = max(res,ans[t]-ans[i-1]);
}
else if(ans[t]-ans[i-1]==res)
{
dong = min(dong,i-1);
}
}
printf("%d\n",dong);
}
return 0;
}