zoukankan      html  css  js  c++  java
  • [BZOJ2138]stone(Hall定理,线段树)

    Description

    话说Nan在海边等人,预计还要等上M分钟。为了打发时间,他玩起了石子。Nan搬来了N堆石子,编号为1到N,每堆
    包含Ai颗石子。每1分钟,Nan会在编号在([L_i,R_i])之间的石堆中挑出任意Ki颗扔向大海(好疼的玩法),如果([L_i,R_i])剩下石子不够(K_i)颗,则取尽量地多。为了保留扔石子的新鲜感,Nan保证任意两个区间([L_i,R_i])([L_j,R_j]),不会存在(L_i<=L_j& R_j<=R_i)的情况,即任意两段区间不存在包含关系。可是,如果选择不当,可能无法扔出最多的石子,这时Nan就会不高兴了。所以他希望制定一个计划,他告诉你他m分钟打算扔的区间([L_i,R_i])以及(K_i)。现在他想你告诉他,在满足前i-1分钟都取到你回答的颗数的情况下,第i分钟最多能取多少个石子。
    (nle 40000)

    Solution

    Hall定理:

    设二分图中( ext{G=< V1,V2,E >})( ext{|V1|=m<=|V2|=n}) ,( ext{G})中存在从 ( ext{V1})( ext{V2})的完全匹配当且仅当( ext{V1})中任意( ext{k(k=1,2,...,m)})个顶点至少与( ext{V2})( ext{k})个顶点是相邻的。

    建立二分图匹配模型,左部节点为石头(每个点拆为A[i]个点),右部节点为需求(每个点拆为K[i]个点),从小到大依次加入右部节点,然后询问在之前需求点匹配数不变的情况下该点最多能匹配的点数。

    不难发现最后是一部分完美匹配+一部分不完美匹配,根据hall定理,一些点具有完美匹配要求任取左部区间,该区间石头数大于等于包含在区间内的需求数。

    那么设 (a[i]) 表示右端点 (le i) 的区间需求量, (b[i]) 为左端点 (le i) 的区间的需求量。

    那么区间 ([l,r])

    石子数 (=s[r] - s[l - 1])
    需求数 (=a[r] - b[l - 1])

    那么只要满足 (forall 0 le i < j le n)

    [(s[j] - s[i]) - (a[j] - b[i]) geq 0 ]

    (f[i] = s[i] - a[i], g[i] = s[i] - b[i])

    考虑区间 ([l,r]) 满足 (k) 的需求量造成的影响。

    [f[r...n] -= k\ g[l...n] -= k ]

    接下来分类讨论,列出不等式:

    [iin [0, l - 1], jin [r + 1, n]\ f[j] - k - g[i] geq 0\ kle min(f[j]) - max(g[i])\ kle min(f[r+1...n]) - max(g[1...l-1]) ]

    (k)(min(f[r+1...n]) - max(g[0...l-1])) 时最优。

    用线段树维护即可。

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <fstream>
    
    typedef long long LL;
    typedef unsigned long long uLL;
    
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define MP(x, y) std::make_pair(x, y)
    #define DE(x) cerr << x << endl;
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define GO cerr << "GO" << endl;
    #define rep(i, a, b) for (register int (i) = (a); (i) <= (b); ++(i))
    
    using namespace std;
    
    inline void proc_status()
    {
    	ifstream t("/proc/self/status");
    	cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;
    }
    inline int read() 
    {
    	register int x = 0; register int f = 1; register char c;
    	while (!isdigit(c = getchar())) if (c == '-') f = -1;
    	while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
    	return x * f;
    }
    template<class T> inline void write(T x) 
    {
    	static char stk[30]; static int top = 0;
    	if (x < 0) { x = -x, putchar('-'); }
    	while (stk[++top] = x % 10 xor 48, x /= 10, x);
    	while (putchar(stk[top--]), top);
    }
    template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
    template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
    
    const int maxN = 4e4;
    
    int n, m;
    int s[maxN + 2], K[maxN + 2];
    
    #define ls (x << 1)
    #define rs (x << 1 | 1)
    #define Rson rs, mid + 1, r
    #define Lson ls, l, mid
    int f[maxN << 2], g[maxN << 2], tagG[maxN << 2], tagF[maxN << 2];
    
    void pushup(int x)
    {
    	f[x] = min(f[ls], f[rs]);
    	g[x] = max(g[ls], g[rs]);
    }
    
    void build(int x, int l, int r)
    {
    	if (l == r) { f[x] = g[x] = s[l]; return; }
    	int mid = l + r >> 1;
    	build(Lson); build(Rson);
    	pushup(x);
    }
    
    void pushG(int x, int k)
    {
    	tagG[x] += k;
    	g[x] += k;
    }
    
    void pushF(int x, int k)
    {
    	tagF[x] += k;
    	f[x] += k;
    }
    
    void pushdown(int x)
    {
    	if (tagG[x] != 0)
    	{
    		pushG(ls, tagG[x]);
    		pushG(rs, tagG[x]);
    		tagG[x] = 0;
    	}
    	if (tagF[x] != 0)
    	{
    		pushF(ls, tagF[x]);
    		pushF(rs, tagF[x]);
    		tagF[x] = 0;
    	}
    }
    
    void addF(int x, int l, int r, int L, int R, int k)
    {
    	if (L <= l and r <= R) { return pushF(x, k); }
    	int mid = l + r >> 1;
    	pushdown(x);
    	if (L <= mid) addF(Lson, L, R, k);
    	if (R > mid) addF(Rson, L, R, k);
    	pushup(x);
    }
    
    void addG(int x, int l, int r, int L, int R, int k)
    {
    	if (L <= l and r <= R) { return pushG(x, k); }
    	int mid = l + r >> 1;
    	pushdown(x);
    	if (L <= mid) addG(Lson, L, R, k);
    	if (R > mid) addG(Rson, L, R, k);
    	pushup(x);
    }
    
    int queryG(int x, int l, int r, int L, int R)
    {
    	if (L <= l and r <= R) { return g[x]; }
    	int mid = l + r >> 1;
    	pushdown(x);
    	int ans = -0x3f3f3f3f;
    	if (L <= mid) chkmax(ans, queryG(Lson, L, R));
    	if (mid < R) chkmax(ans, queryG(Rson, L, R));
    	return ans;
    }
    
    int queryF(int x, int l, int r, int L, int R)
    {
    	if (L <= l and r <= R) { return f[x]; }
    	int mid = l + r >> 1;
    	pushdown(x);
    	int ans = 0x3f3f3f3f;
    	if (L <= mid) chkmin(ans, queryF(Lson, L, R));
    	if (mid < R) chkmin(ans, queryF(Rson, L, R));
    	return ans;
    }
    
    int main() 
    {
    #ifndef ONLINE_JUDGE
    	freopen("stone.in", "r", stdin);
    	freopen("stone.out", "w", stdout);
    #endif
    	int x, y, z, P;
    	scanf("%d", &n);
    	scanf("%d%d%d%d", &x, &y, &z, &P);
    	for (int i = 1; i <= n; ++i)
    		s[i] = s[i - 1] + ((i - x) * (i - x) + (i - y) * (i - y) + (i - z) * (i - z)) % P;
    	scanf("%d", &m);
    	scanf("%d%d%d%d%d%d", &K[1], &K[2], &x, &y, &z, &P);
    	for (int i = 3; i <= m; ++i)
    		K[i] = (1ll * x * K[i - 1] + 1ll * y * K[i - 2] + z) % P;
    	build(1, 0, n);
    	for (int i = 1; i <= m; ++i)
    	{
    		int L, R, k;
    		scanf("%d%d", &L, &R);
    		printf("%d
    ", k = min(queryF(1, 0, n, R, n) - queryG(1, 0, n, 0, L - 1), K[i]));
    		addF(1, 0, n, R, n, -k);
    		addG(1, 0, n, L, n, -k);
    	}
    	return 0;
    }
    
  • 相关阅读:
    人工智能背后的故事
    idea 开发插件。
    安卓工作室 Android studio 或 Intellij IDEA 美化 修改 汉化 酷炫 装逼 Android studio or Intellij IDEA beautify modify Chinesization cool decoration
    安卓工作室 android studio文件和代码模板,以及汉化出错问题
    安卓工作室 android studio 汉化后,报错。 设置界面打不开。Can't find resource for bundle java.util.PropertyResourceBundle, key emmet.bem.class.name.element.separator.label
    android studio的汉化 教程 及解析
    安卓工作室Android Studio 快捷键
    安卓工作室 android studio 的 汉化 美化 定制 Android studio's Chinesization beautification customization
    VR开发 VR development
    Lakeshore 中文开发界面,示例项目,飞机大战 等 Lakeshore Chinese development interface, sample project, aircraft war, etc
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/11439760.html
Copyright © 2011-2022 走看看