zoj 5823 Soldier Game 2018 青岛 I
题意:现在有n个人,现在可以把这n个人分成若干组,只有连续的人才能被分为一组,并且一个组内最多2个人,现在问你 所有组内的最大值-最小值 这个差值最小是多少。
题解:
将每个人的情况3种情况都拿出来,把这些所有的情况从小到大排序,然后我们枚举起点,然后一直不停的添加线段,然后直到当前的区间内的所有线段,我们可以选择其中的一部分,使得这些线段能够不重合的前提下巧好覆盖1-n的区间内。
tree[x] 假设管理的区间为 [l, r] tree[x][i][j] i代表的是左端点 j 代表的是右端点, 当i == 1 的时候,j == 1的时候,我们管理的是 [l+1,r+1]这个区间的状态 i == 0,j == 0 管理的是 [l, r]这个区间的状态。
所以我们pushup的时候不重合的搞就好了。
代码:
#include<bits/stdc++.h> using namespace std; #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); #define LL long long #define ULL unsigned LL #define fi first #define se second #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = (int)1e9+7; const int N = 1e5 + 100; int a[N][2]; pll p[N<<1]; bool cmp(pll & x, pll & y){ return a[x.fi][x.se] < a[y.fi][y.se]; } int tree[N<<2][2][2]; void Build(int l, int r, int rt){ tree[rt][0][0] = tree[rt][0][1] = tree[rt][1][0] = tree[rt][1][1] = 0; if(l == r) { tree[rt][1][0] = 1; return ; } int m = l+r >> 1; Build(lson); Build(rson); } void PushUp(int rt){ tree[rt][0][0] = (tree[rt<<1][0][0] && tree[rt<<1|1][0][0]) || (tree[rt<<1][0][1] && tree[rt<<1|1][1][0]); tree[rt][0][1] = (tree[rt<<1][0][0] && tree[rt<<1|1][0][1]) || (tree[rt<<1][0][1] && tree[rt<<1|1][1][1]); tree[rt][1][0] = (tree[rt<<1][1][0] && tree[rt<<1|1][0][0]) || (tree[rt<<1][1][1] && tree[rt<<1|1][1][0]); tree[rt][1][1] = (tree[rt<<1][1][1] && tree[rt<<1|1][1][1]) || (tree[rt<<1][1][0] && tree[rt<<1|1][0][1]); } void Update(int L, int op,int l, int r, int rt){ if(l == r){ tree[rt][0][op] ^= 1; return ; } int m = l+r >> 1; if(L <= m) Update(L, op, lson); else Update(L, op, rson); PushUp(rt); } int main(){ int T, n; scanf("%d", &T); while(T--){ scanf("%d", &n); int m = 0; for(int i = 1; i <= n; ++i){ scanf("%d", &a[i][0]); p[++m] = pll(i,0); if(i-1) { a[i-1][1] = a[i-1][0] + a[i][0]; p[++m] = pll(i-1,1); } } sort(p+1, p+1+m, cmp); Build(1,n,1); LL ans = INF; for(int i = 1, j=1; i <= m; ++i){ while(j <= m && !tree[1][0][0]){ Update(p[j].fi, p[j].se, 1, n, 1); j++; } if(tree[1][0][0]) ans = min(ans, 1ll*a[p[j-1].fi][p[j-1].se] - a[p[i].fi][p[i].se]); Update(p[i].fi, p[i].se, 1, n, 1); } printf("%lld\n", ans); } return 0; }