[BZOJ1135][P3488][POI2009]LYZ[线段树+Hall定理]

首先从二分图匹配的角度来想这个题,只要每个人都能和一双鞋子匹配,那么溜冰鞋就是足够的。

但看范围不能用二分图匹配来做,因为边数会爆炸

Hall定理是判定二分图是否存在完全匹配的定理。

完全匹配:是指最大匹配数为 \(min(|X|,|Y|)\) 也就是 \(X\)\(Y\) 集合其中一个集合所有点都被匹配了。

设二分图\(G=\lt V\text{1,}V\text{2,}E\gt\)\(|V\text{1|}=m<=|V\text{2|}=n\)
, \(G\) 中存在从 \(V1\)\(V2\) 的完全匹配当且仅当 \(V1\) 中任意 \(k(k=1,2,...,m)\) 个顶点至少与 \(V2\)\(k\) 个顶点是相邻的。
有解的条件就是任意一个人的集合的人数<=所连接的鞋子数量

\(r_i\)是连续的时候连接的鞋子的数量最少。
TIM截图20180710161707.png
TIM截图20180710161727.png
所以如果连续的情况满足,其他情况一定满足。

关于为什么最坏情况不满足,其他情况就一定不满足,不是很懂,翻了好多题解都没有看到关于这个的解释。求解

上述成立的话,就是带修改维护最大子段和了

\[\sum_{i=l}^r{\{}a\left[ i \right] \le \,\,\left( r-l+1+d \right) *k\} \]

\[\sum_{i=l}^r{\left( a\left[ i \right] -k \right) \le d*k} \]

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
 
bool Debug;
 
const int mod = 1e9+7;
const int MAXN = 2e5+7;

#define xx first
#define yy second
#define pb push_back
#define mp make_pair
#define iter iterator
#define sqr(a) ((a)*(a))
#define abs(a) ((a)>0?(a):(-(a)))
#define max(a, b) ((a)>(b)?(a):(b))
#define min(a, b) ((a)<(b)?(a):(b))
#define mset(a, b) memset(a, b, sizeof(a))
#define mcpy(a, b) memcpy(a, b, sizeof(a))
#define lop(i,a,b) for(int i = (a); i <= (b); ++i)
#define dlop(i,a,b) for(int i = (a); i >= (b); --i)
#define debu(...) if (Debug) fprintf(stderr, __VA_ARGS__)
#define debug(x) if (Debug) cerr << "" #x " = " << x << endl
#define ergo(a) for(auto it = a.begin(); it != a.end(); ++it)
 
template<typename T> T gcd(T a, T b) {T t; while(t = a % b) a = b, b = t; return b;}
template<typename T> T Pow(T a, T b, T mod) {T ret = 1; for( ; b; b >>= 1) {if (b & 1) ret = ret * 1ull * a % mod; a = a * 1ull * a % mod;} return ret%mod;}
template<typename T> void chmax(T &x, T y) {if (x < y) x = y;}
template<typename T> void chmin(T &x, T y) {if (x > y) x = y;}
template<typename T> void amod(T &x, T y) {x += y; if (x >= mod) x -= mod;}
template<typename T> void smod(T &x, T y) {x -= y; if (x < 0) x += mod;}
 
typedef long long ll; 
typedef long double ld;
typedef unsigned int uint;
typedef pair<int,int> pii;
typedef unsigned long long ull;
template<typename T> void read(T &x) {
  x = 0; int c = getchar(), f = 1;
  while(!isdigit(c)) (c=='-')&&(f = -1), c = getchar();
  while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
  x *= f;
}
#define read2(a, b) read(a), read(b)
ll n, a[200005], m, k, d, x, y;
 
struct Node{
  ll lmax, rmax, tmax, val;
  Node *ls, *rs;
  inline void pushup(){
    val = ls->val + rs->val;
    lmax = max(ls->lmax, ls->val + rs->lmax);
    rmax = max(rs->rmax, rs->val + ls->rmax);
    tmax = max(ls->tmax, max(rs->tmax, ls->rmax + rs->lmax));
  }
}pool[MAXN<<1], *root;
inline Node *newNode() {
  static int cnt = 0;
  return &pool[cnt++];
}
 
Node *build(int l, int r) {
  Node *cur = newNode();
  if (l != r) {
    int mid = l+r>>1;
    cur->ls = build(l, mid);
    cur->rs = build(mid+1, r);
    cur->pushup();
  }
  else cur->val = cur->tmax = -k;
  return cur;
}
 
void Modify(Node *cur, int l, int r, int x, int y) {
  if (l == r) {
    cur->val += y, cur->tmax += y; 
    cur->lmax = cur->rmax = max(cur->val, 0);
    return ;
  }
  int mid = l+r>>1;
  if (x <= mid) Modify(cur->ls, l, mid, x, y);
  else Modify(cur->rs, mid+1, r, x, y);
  cur->pushup();
}
 
int main() {
  #ifdef LOCAL_DEBUG
    Debug = 1;
    // freopen("data.in", "r", stdin);
    // freopen("data.out", "w", stdout);
  #endif
  read2(n, m), read2(k, d);
  root = build(1, n);
  while(m--) {
    read2(x, y);
//    cerr << x << ' ' << y << endl;
    Modify(root, 1, n, x, y);
    if (root->tmax <= k * d) puts("TAK");
    else puts("NIE");
  }
//  cout << root->tmax;
  return 0;
}
posted @ 2018-12-28 16:03  QvvQ  阅读(234)  评论(0编辑  收藏  举报