BZOJ1135 LYZ(POI2009) Hall定理+线段树

 

 做这个题之前首先要了解判定二分图有没有完备匹配的Hall定理:

 

 那么根据Hell定理,如果任何一个X子集都能连大于等于|S|的Y子集就可以获得完备匹配,那么就是:

BZOJ1135 LYZ(POI2009) Hall定理+线段树_第1张图片

 

题目变成只要不满足上面这个条件就能得到完备匹配,注意到右边的这个dk是一个常数,那么我们就可以只考虑左边最大的是否满足就行了。

那么我们就可以在修改过程中一边在线段树上修改一边查询区间最大值作比较就可以了。

 1 #include 
 2 using namespace std;
 3 const int N=800010;
 4 typedef long long ll;
 5 int n,m;
 6 ll k,d,sum[N],lftsum[N],rhtsum[N],mxsum[N];
 7 
 8 void buildtree(int no,int l,int r) {
 9     lftsum[no]=rhtsum[no]=mxsum[no]=0;
10     if (l==r) {sum[no]=-k;return;}
11     int mid=(l+r)>>1;
12     buildtree(no<<1,l,mid);
13     buildtree(no<<1|1,mid+1,r);
14     sum[no]=sum[no<<1]+sum[no<<1|1];
15 }
16 
17 void pushup(int no) {
18     sum[no]=sum[no<<1]+sum[no<<1|1];
19     mxsum[no]=max(max(mxsum[no<<1],mxsum[no<<1|1]),rhtsum[no<<1]+lftsum[no<<1|1]);
20     lftsum[no]=max(lftsum[no<<1],lftsum[no<<1|1]+sum[no<<1]);
21     rhtsum[no]=max(rhtsum[no<<1|1],rhtsum[no<<1]+sum[no<<1|1]);
22 }
23 
24 void modify(int no,int l,int r,int pos,ll x) {
25     if (l==r) {
26         sum[no]+=x;
27         lftsum[no]=rhtsum[no]=mxsum[no]=max(sum[no],(ll)0);
28         return;
29     }
30     int mid=(l+r)>>1;
31     if (pos<=mid) modify(no<<1,l,mid,pos,x);
32     else modify(no<<1|1,mid+1,r,pos,x);
33     pushup(no);
34 }
35 
36 int main()
37 {
38     scanf("%d%d%lld%lld",&n,&m,&k,&d);
39     buildtree(1,1,n-d);
40     for(int i=1;i<=m;i++) {
41         int r;
42         ll x;
43         scanf("%d%lld",&r,&x);
44         modify(1,1,n-d,r,x);
45         if (mxsum[1]>d*k) printf("NIE\n");
46         else printf("TAK\n");
47     }
48     return 0;
49 }

 

你可能感兴趣的:(BZOJ1135 LYZ(POI2009) Hall定理+线段树)