C
相邻前缀不相同就是没有0
只有+-+-+-和-+-+-+两种情况,枚举
每个位置加减会改变后面所有前缀和,所以这个位置只要修改到符合符号就行了
D
(打表)发现|X-Y|<=1时先手必败
E
记从1开始走到i时刻前距离终点di,发现witch就是把di+1变成0~di的一个数
维护一个最大的now表示i这个时刻后,距离终点0~now都一定能到达终点,i=n时now=0,然后从n往前递推,
当ai<=now+1或ai>now+1且ai-(now+1)<=now时now+=ai,
否则now不变,
di>now时witch能让他变成now+1使其不能到达终点
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 610000;
int n,Q,D,ed;
int a[maxn],d[maxn];
int ok[maxn];
int main()
{
scanf("%d%d",&n,&D);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int tmp=D;
for(int i=1;i<=n;i++) if(a[i]<tmp*2)
{
d[i]=tmp;
tmp=a[i]>tmp?a[i]-tmp:tmp-a[i];
if(!tmp) { ed=i; break; }
}
if(tmp) for(int i=1;i<=n;i++) ok[i]=1;
else
{
int now=0;
for(int i=n;i>=1;i--)
{
int x=a[i+1];
if((x-(now+1)<=now)) now+=x;
if(ed<i) { ok[i]=0; continue; }
if(d[i]>now) ok[i]=1;
}
}
scanf("%d",&Q);
while(Q--)
{
int x; scanf("%d",&x);
puts(ok[x]?"YES":"NO");
}
return 0;
}
F
用一个二元组(x,y)表示水量有x升,x*temperature=y,的状态,
维护第i天水量为j的最大温度f[i][j],将f[i][j]表示在二维平面上,j为横坐标,f[i][j]为纵坐标,发现是一些折线,比如f[1][L]就是一条连接(0,0)和(v,vt)的线段。
每一天,会在头部连上一条线段,可以发现维护一个上凸的凸包一定保证每个j的f[i][j]最优
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 510000;
int n,L;
struct node{double x,y;}a[maxn<<1]; int head,tail;
double multi(node x,node y,node z)
{
x.x-=z.x; x.y-=z.y;
y.x-=z.x; y.y-=z.y;
return x.x*y.y-x.y*y.x;
}
int main()
{
scanf("%d%d",&n,&L); n--;
a[head=maxn]=(node){0.0,0.0};
ll x,y;
tail=head+1; scanf("%lld%lld",&y,&x);
printf("%lf\n",(double)y); a[tail].y=(double)x*y; a[tail].x=x;
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&y,&x); y*=x;
node now=(node){a[head].x-(double)x,a[head].y-(double)y};
while(head+1<=tail&&a[tail-1].x-now.x>=L) tail--;
if(head!=tail)
{
double pt=(a[tail].y-a[tail-1].y)/(a[tail].x-a[tail-1].x);
if(a[tail].x-now.x>L)
{
a[tail].y=a[tail-1].y+(L-(a[tail-1].x-now.x))*pt;
a[tail].x=now.x+L;
}
}
while(head+1<=tail&&multi(a[head],a[head+1],now)>=0) head++;
a[--head]=now;
double kk=a[tail].y-now.y;
printf("%lf\n",kk/(double)L);
}
return 0;
}