可以看成一张二分图,判断左半部分是否存在完美匹配
根据hall定理,当且仅当左半部分每一个子集所连向的点数量超过了这个子集的大小
都判定复杂度肯定爆炸,可以贪心,一定选择的是一个区间,即对于任意区间[l,r],都要满足$sum_{i=l}^{r}aile (r-l+1+d)k$(ai表示i号鞋子的人数),化简得到$sum_{i=l}^{r}(ai-k)le kd$,kd都是定值,因此相当于要维护$ai-k$的最大字段和,线段树即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000005 4 #define ll long long 5 #define L (k<<1) 6 #define R (L+1) 7 #define mid (l+r>>1) 8 int n,m,x,y; 9 ll k,ls[N],rs[N],sum[N],f[N]; 10 void update(int k,int l,int r,int x,int y){ 11 if (l==r){ 12 ls[k]+=y; 13 rs[k]+=y; 14 sum[k]+=y; 15 f[k]+=y; 16 return; 17 } 18 if (x<=mid)update(L,l,mid,x,y); 19 else update(R,mid+1,r,x,y); 20 ls[k]=max(ls[L],sum[L]+ls[R]); 21 rs[k]=max(rs[R],sum[R]+rs[L]); 22 sum[k]=sum[L]+sum[R]; 23 f[k]=max(max(f[L],f[R]),rs[L]+ls[R]); 24 } 25 int main(){ 26 scanf("%d%d%d%d",&n,&m,&x,&y); 27 for(int i=1;i<=n;i++)update(1,1,n,i,-x); 28 k=1LL*x*y; 29 for(int i=1;i<=m;i++){ 30 scanf("%d%d",&x,&y); 31 update(1,1,n,x,y); 32 if (f[1]<=k)printf("TAK "); 33 else printf("NIE "); 34 } 35 }