懒癌
先考虑-1的情况,如果一个人知道了自己是特殊的位置,但是(b>c),那么就无法判断了
其次,我们考虑一开始有一个不合法的(a)的集合,也就是没有特殊位置的集合(f_0)
如果在时间(1),某一个人的视角下刚好和这个特殊位置重合了(就是除他自己的颜色),那么它就可以报出这个不合法的情况,游戏结束。
如果在时间(1)没有发现爆炸,所有人可以得到新的信息:没有人刚好重合。那么此时可以扩展不合法的集合,改变其中的(f_0)中任何一个(a)的一个位置,在此时仍是不合法的。
以此类推,每个时间过去获得信息并扩展不合法的集合。
现在给了你一个(a),需要求出它出现的最小时间。
考虑一个不合法集合是什么样子的
[a_i+b_ile a_{i+1}le a_i+c_i
]
那么可以通过改变最少的(a)来达到这个不合法集合(因为每个时间可以变动一个位置)
把条件变一下,令(B_i,C_i)代表前缀和(向右移动一位)
那么可以变成对无序二元组((i,j))有
[a_i-B_ile a_j-B_j\
a_i-C_ige a_j-C_j
]
可以投影到二维平面做最长不上升子序列
Code:
#include <cstdio>
#include <cctype>
#include <algorithm>
#define ll long long
const int N=1e5+10;
template <class T>
void read(T &x)
{
int f=0;x=0;char c=getchar();
while(!isdigit(c)) f|=c=='-',c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
if(f) x=-x;
}
int n,cnt;
ll a[N],b[N],c[N],bee[N];
struct koito_yuu
{
ll a,b;
koito_yuu(){}
koito_yuu(ll A,ll B){a=A,b=B;}
bool friend operator <(koito_yuu a,koito_yuu b){return a.a>b.a;}
}yuu[N];
int main()
{
freopen("pjz.in","r",stdin);
freopen("pjz.out","w",stdout);
read(n);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=2;i<=n;i++) read(b[i]);
for(int i=2;i<=n;i++) read(c[i]);
for(int i=2;i<=n;i++)
if(b[i]>c[i])
{
puts("-1");
return 0;
}
for(int i=2;i<=n;i++) b[i]+=b[i-1],c[i]+=c[i-1];
for(int i=1;i<=n;i++) yuu[i]=koito_yuu(a[i]-b[i],a[i]-c[i]);
std::sort(yuu+1,yuu+1+n);
for(int i=1;i<=n;i++)
{
if(!cnt||yuu[i].b>=bee[cnt]) bee[++cnt]=yuu[i].b;
else bee[std::upper_bound(bee+1,bee+1+cnt,yuu[i].b)-bee]=yuu[i].b;
}
printf("%d
",n-cnt);
return 0;
}
2019.3.31