zoukankan      html  css  js  c++  java
  • UOJ Round #19 简要题解

    从这里开始

    自闭记

      自闭的丢人组选手不配拥有游记。

    • 打到一半看到 t3 一堆 100,以为全是写的一个 log,比赛结束后,随便点开了若干份代码。今天是愚人节吗?今天不是清明节吗。。。
    • 然后以为难度是倒序,打完发现 AB 都是签到。签到失败 * 2,自闭了。

    Problem A 清扫银河

      你发现操作是两个:

    • 选一个环,所有边翻转状态
    • 选一个点,翻转周围的状态

      第一类操作至多操作 $m$ 次,第二类至多操作一次,所以问题变成判定是否有解。对第一类操作搞一个生成树。于是我们有了 $O(frac{Tm^3}{64})$ 的优秀做法。

      注意到返祖边最多在 3 个地方出现,把环的那一行的返祖边那一位作为主元,消掉剩下两处。

      然后变量数就只有树边数了。

      然后就有了一个 $O(Tn^3)$ 的辣鸡做法。

      upd:做一个树上前缀和就可以 $O(frac{Tn^3}{64}) $ 辣。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    template <typename T>
    boolean vmin(T& a, T b) {
    	return (a > b) ? (a = b, true) : (false);
    }
    template <typename T>
    boolean vmax(T& a, T b) {
    	return (a < b) ? (a = b, true) : (false);
    }
    
    template <typename T>
    T smax(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smax(T a, const K &...args) {
    	return max(a, smax(args...));
    }
    
    template <typename T>
    T smin(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smin(T a, const K &...args) {
    	return min(a, smin(args...));
    }
    
    // debugging lib
    
    #define VN(x) #x
    #define Vmsg(x) VN(x) << " = " << (x)
    #define printv(x) cerr << VN(x) << " = " << (x);
    #define debug(...) fprintf(stderr, __VA_ARGS__);
    
    template <typename A, typename B>
    ostream& operator << (ostream& os, const pair<A, B>& z) {
    	os << "(" << z.first << ", " << z.second << ')';
    	return os;
    }
    template <typename T>
    ostream& operator << (ostream& os, const vector<T>& a) {
    	boolean isfirst = true;
    	os << "{";
    	for (auto z : a) {
    		if (!isfirst) {
    			os << ", ";
    		}
    		os << z;
    		isfirst = false;
    	}
    	os << '}';
    	return os;
    }
    
    #define pii pair<int, int>
    #define pil pair<int, ll>
    #define pli pair<ll, int>
    #define ll long long
    #define ull unsigned long long
    
    const int inf = (signed) (~0u >> 2);
    const ll llf = (signed ll) (~0ull >> 2);
    
    #define pb push_back
    #define eb emplace_back
    #define fi first
    #define sc second
    
    template <typename T>
    int vsize(vector<T>& x) {
    	return (signed) x.size(); 
    }
    
    template <typename T>
    int discrete(T* a, int* b, int n) {
        vector<T> v(a + 1, a + n + 1);
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    	for (int i = 1; i <= n; i++) b[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    	return v.size();
    }
    
    mt19937 rng (time(NULL));
    
    int randint(int l, int r) {
    	return rng() % (r - l + 1) + l;
    }
    
    const int N = 305, M = N * N;
    
    typedef bitset<N> bit;
    
    int T;
    int n, m;
    int tid[M];
    vector<pii> G[N];
    
    typedef class LinearBasis {
    	public:
    		bit a[N];
    		
    		bool insert(bit v) {
    			for (int i = n - 1; i--; ) {
    				if (v.test(i)) {
    					v ^= a[i];
    				}
    				if (v.test(i)) {
    					a[i] = v;
    					return true;
    				}
    			} 
    			return false;
    		}
    		void clear() {
    			for (int i = 0; i < n; i++) {
    				a[i].reset();
    			}
    		}
    } LinearBasis;
    
    int cnte = 0;
    bit qbit;
    bit bnear[N];
    bitset<N * N> _qbit;
    bool vis[N];
    int fa[N], fae[N], dep[N];
    
    LinearBasis lb;
    
    void dfs1(int p, int _fa, int _fae) {
    	fa[p] = _fa;
    	fae[p] = _fae;
    	vis[p] = true;
    	dep[p] = dep[_fa] + 1;
    	if (~_fae) {
    		tid[_fae] = cnte++;
    	}
    	for (auto _ : G[p]) {
    		int e = _.fi;
    		int id = _.sc;
    		if (id == _fae) {
    			continue;
    		}
    		if (!vis[e]) {
    			dfs1(e, p, id);
    		}
    	}
    }
    
    void dfs2(int p) {
    	static bit b;
    	for (auto _ : G[p]) {
    		int e = _.fi;
    		int id = _.sc;
    		if (e == fa[p]) {
    			continue;
    		}
    		if (~tid[id]) {
    			dfs2(e);
    		} else if (dep[e] < dep[p]) {
    			b.reset();
    			for (int q = p; q ^ e; q = fa[q]) {
    				b.set(tid[fae[q]]);
    			}
    			if (_qbit.test(id)) {
    				_qbit.flip(id);
    				for (int q = p; q ^ e; q = fa[q]) {
    					_qbit.flip(fae[q]);
    				}
    			}
    			bnear[e] ^= b;
    			bnear[p] ^= b;
    		}
    	}
    }
    
    void solve() {
    	cin >> n >> m;
    	cnte = 0;
    	qbit.reset();
    	_qbit.reset();
    	fill(tid, tid + m, -1);
    	for (int i = 0, u, v, c; i < m; i++) {
    		cin >> u >> v >> c;
    		if (c == 1) {
    			_qbit.set(i);
    		}
    		G[u].eb(v, i);
    		G[v].eb(u, i);
    	}
    	for (int i = 1; i <= n; i++) {
    		bnear[i].reset();
    	}
    	for (int i = 1; i <= n; i++) {
    		if (!vis[i]) {
    			dfs1(i, 0, -1);
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		for (auto e : G[i]) {
    			if (~tid[e.sc]) {
    				bnear[i].set(tid[e.sc]);
    			}
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		if (!fa[i]) {
    			dfs2(i);
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		lb.insert(bnear[i]);
    	}
    	for (int i = 0; i < m; i++) {
    		if (_qbit.test(i)) {
    			assert(tid[i] >= 0);
    			qbit.set(tid[i]);
    		}
    	}
    	if (lb.insert(qbit)) {
    		cout << "no" << '
    ';
    	} else {
    		cout << "yes" << '
    ';
    	}
    }
    
    void clear() {
    	fill(vis, vis + n + 1, false);
    	lb.clear();
    	for (int i = 1; i <= n; i++) {
    		G[i].clear();
    	}
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	cin >> T;
    	while (T--) {
    		solve();
    		clear();
    	}
    	return 0;
    }
    

      考虑所有环的形成空间有什么性质。考虑随便拿一组标为 1 的边集,如果包含某条返祖边就异或上它。最后要在生成树上不剩任何边。不难证明这个条件是初始每个点的度数为偶数。

      因此只用让每个点的度数为偶数就行了。变量数只有 $n$ 个了。

      时间复杂度 $O(frac{Tn^3}{64})$。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    template <typename T>
    boolean vmin(T& a, T b) {
    	return (a > b) ? (a = b, true) : (false);
    }
    template <typename T>
    boolean vmax(T& a, T b) {
    	return (a < b) ? (a = b, true) : (false);
    }
    
    template <typename T>
    T smax(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smax(T a, const K &...args) {
    	return max(a, smax(args...));
    }
    
    template <typename T>
    T smin(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smin(T a, const K &...args) {
    	return min(a, smin(args...));
    }
    
    // debugging lib
    
    #define VN(x) #x
    #define Vmsg(x) VN(x) << " = " << (x)
    #define printv(x) cerr << VN(x) << " = " << (x);
    #define debug(...) fprintf(stderr, __VA_ARGS__);
    
    template <typename A, typename B>
    ostream& operator << (ostream& os, const pair<A, B>& z) {
    	os << "(" << z.first << ", " << z.second << ')';
    	return os;
    }
    template <typename T>
    ostream& operator << (ostream& os, const vector<T>& a) {
    	boolean isfirst = true;
    	os << "{";
    	for (auto z : a) {
    		if (!isfirst) {
    			os << ", ";
    		}
    		os << z;
    		isfirst = false;
    	}
    	os << '}';
    	return os;
    }
    
    #define pii pair<int, int>
    #define pil pair<int, ll>
    #define pli pair<ll, int>
    #define ll long long
    #define ull unsigned long long
    
    const int inf = (signed) (~0u >> 2);
    const ll llf = (signed ll) (~0ull >> 2);
    
    #define pb push_back
    #define eb emplace_back
    #define fi first
    #define sc second
    
    template <typename T>
    int vsize(vector<T>& x) {
    	return (signed) x.size(); 
    }
    
    template <typename T>
    int discrete(T* a, int* b, int n) {
        vector<T> v(a + 1, a + n + 1);
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    	for (int i = 1; i <= n; i++) b[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    	return v.size();
    }
    
    mt19937 rng (time(NULL));
    
    int randint(int l, int r) {
    	return rng() % (r - l + 1) + l;
    }
    
    const int N = 305;
    
    typedef bitset<N> bit;
    
    int T;
    int n, m;
    
    typedef class LinearBasis {
    	public:
    		bit a[N];
    		
    		bool insert(bit v) {
    			for (int i = n - 1; i--; ) {
    				if (v.test(i)) {
    					v ^= a[i];
    				}
    				if (v.test(i)) {
    					a[i] = v;
    					return true;
    				}
    			} 
    			return false;
    		}
    		void clear() {
    			for (int i = 0; i < n; i++) {
    				a[i].reset();
    			}
    		}
    } LinearBasis;
    
    bit G[N], qbit;
    LinearBasis lb;
    
    void solve() {
    	cin >> n >> m;
    	qbit.reset();
    	for (int i = 0; i < n; i++) {
    		G[i].reset();
    	}
    	for (int i = 0, u, v, c; i < m; i++) {
    		cin >> u >> v >> c;
    		--u, --v;
    		if (c == 1) {
    			qbit.flip(u);
    			qbit.flip(v);
    		}
    		G[u].flip(u);
    		G[u].flip(v);
    		G[v].flip(u);
    		G[v].flip(v);
    	}
    	for (int i = 0; i < n; i++) {
    		lb.insert(G[i]);
    	}
    	if (lb.insert(qbit)) {
    		cout << "no" << '
    ';
    	} else {
    		cout << "yes" << '
    ';
    	}
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	cin >> T;
    	while (T--) {
    		solve();
    		lb.clear();
    	}
    	return 0;
    }

    Problem B 通用测评号 

      20 分做法:写一个四方 dp,然后组合数只预处理到 $n$,rk 6 → rk 18.

      不难发现,如果放满了,继续放不会改变答案。

      考虑计算 $1$ 未被填满的概率。考虑枚举最后填上的是哪一个。

      如果是 $1$,然后容斥计算填最后一个后,剩下哪些还没有填满。

      假设一共有 $k$ 个位置没有填满,它们一共填了 $x$ 个,那么每个前后都可以放上一些未被硬点的位置的填东西操作。对于填一处的操作需要乘上 $frac{1}{1 - frac{n - k}{n}} = frac{n}{k}$。所以总共要乘上 $left(frac{n}{k} ight) ^{x + 1}$。

      如果不是 $1$,假设最后填上的是 $2$,那么枚举一下 $1$ 填了多少个。

      剩下是一个背包,暴力实现可以四方,NTT 优化可以三方乘 log。实际上这可以做到三方

      问题等价于将 $j$ 个带标号东西分给 $i$ 个带标号的人,每个人拿到的东西少于 $b$ 个问方案数。

      考虑枚举物品,每次任意扔给一个人,如果不合法,那么枚举哪些东西是扔给它的 $b$ 个,减去这些方案就行了。

      第二部分稍有些不同的在于要求第一个人拿到少于 $a$,显然你可以在 dp 中简单处理一下。

      时间复杂度 $O(n^3)$。

      Emmm....感觉自己啥都记不到了。

      可以发现这个东西实际上是 $F(x) = sum_{i = 0}^{b - 1}  frac{x^i}{i!}$ 求 $k$ 次幂。考虑 $F'(x) = F(x) - frac{x^{b - 1}}{(b - 1)!}$。

      设 $G(x) = F^k(x)$,对两边求导得 $G'(x) = kF^{k - 1}(x)F'(x) = kG(x) - k frac{x^{b - 1}}{(b - 1)!}F^{k - 1}(x)$。按位推就行了。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    template <typename T>
    boolean vmin(T& a, T b) {
    	return (a > b) ? (a = b, true) : (false);
    }
    template <typename T>
    boolean vmax(T& a, T b) {
    	return (a < b) ? (a = b, true) : (false);
    }
    
    template <typename T>
    T smax(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smax(T a, const K &...args) {
    	return max(a, smax(args...));
    }
    
    template <typename T>
    T smin(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smin(T a, const K &...args) {
    	return min(a, smin(args...));
    }
    
    // debugging lib
    
    #define VN(x) #x
    #define Vmsg(x) VN(x) << " = " << (x)
    #define printv(x) cerr << VN(x) << " = " << (x);
    #define debug(...) fprintf(stderr, __VA_ARGS__);
    
    template <typename A, typename B>
    ostream& operator << (ostream& os, const pair<A, B>& z) {
    	os << "(" << z.first << ", " << z.second << ')';
    	return os;
    }
    template <typename T>
    ostream& operator << (ostream& os, const vector<T>& a) {
    	boolean isfirst = true;
    	os << "{";
    	for (auto z : a) {
    		if (!isfirst) {
    			os << ", ";
    		}
    		os << z;
    		isfirst = false;
    	}
    	os << '}';
    	return os;
    }
    
    #define pii pair<int, int>
    #define pil pair<int, ll>
    #define pli pair<ll, int>
    #define ll long long
    #define ull unsigned long long
    
    const int inf = (signed) (~0u >> 2);
    const ll llf = (signed ll) (~0ull >> 2);
    
    #define pb push_back
    #define eb emplace_back
    #define fi first
    #define sc second
    
    template <typename T>
    int vsize(vector<T>& x) {
    	return (signed) x.size(); 
    }
    
    template <typename T>
    int discrete(T* a, int* b, int n) {
        vector<T> v(a + 1, a + n + 1);
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    	for (int i = 1; i <= n; i++) b[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    	return v.size();
    }
    
    mt19937 rng (time(NULL));
    
    int randint(int l, int r) {
    	return rng() % (r - l + 1) + l;
    }
    
    #define ll long long
    
    void exgcd(int a, int b, int& x, int& y) {
    	if (!b) {
    		x = 1, y = 0;
    	} else {
    		exgcd(b, a % b, y, x);
    		y -= (a / b) * x;
    	}
    }
    
    int inv(int a, int n) {
    	int x, y;
    	exgcd(a, n, x, y);
    	return (x < 0) ? (x + n) : (x);
    }
    
    const int Mod = 998244353;
    
    template <const int Mod = :: Mod>
    class Z {
    	public:
    		int v;
    
    		Z() : v(0) {	}
    		Z(int x) : v(x){	}
    		Z(ll x) : v(x % Mod) {	}
    
    		friend Z operator + (const Z& a, const Z& b) {
    			int x;
    			return Z(((x = a.v + b.v) >= Mod) ? (x - Mod) : (x));
    		}
    		friend Z operator - (const Z& a, const Z& b) {
    			int x;
    			return Z(((x = a.v - b.v) < 0) ? (x + Mod) : (x));
    		}
    		friend Z operator * (const Z& a, const Z& b) {
    			return Z(a.v * 1ll * b.v);
    		}
    		friend Z operator ~(const Z& a) {
    			return inv(a.v, Mod);
    		}
    		friend Z operator - (const Z& a) {
    			return Z(0) - a;
    		}
    		Z& operator += (Z b) {
    			return *this = *this + b;
    		}
    		Z& operator -= (Z b) {
    			return *this = *this - b;
    		}
    		Z& operator *= (Z b) {
    			return *this = *this * b;
    		}
    		friend boolean operator == (const Z& a, const Z& b) {
    			return a.v == b.v;
    		} 
    };
    
    Z<> qpow(Z<> a, int p) {
    	Z<> rt = Z<>(1), pa = a;
    	for ( ; p; p >>= 1, pa = pa * pa) {
    		if (p & 1) {
    			rt = rt * pa;
    		}
    	}
    	return rt;
    }
    
    typedef Z<> Zi;
    
    const int N = 255;
    
    int n, a, b, m;
    Zi f[N][N * N];
    Zi g[N][N * N];
    Zi fac[N * N], _fac[N * N];
    
    Zi comb(int n, int m) {
    	return (n < m) ? 0 : fac[n] * _fac[m] * _fac[n - m];
    }
    
    void prepare(int n) {
    	fac[0] = 1;
    	for (int i = 1; i <= n; i++) {
    		fac[i] = fac[i - 1] * i;
    	}
    	_fac[n] = ~fac[n];
    	for (int i = n; i; i--) {
    		_fac[i - 1] = _fac[i] * i;
    	}
    }
    
    void work_f(int n) {
    	int m = n * (b - 1);
    	for (int i = 0; i <= n; i++) {
    		f[i][0] = 1;
    	}
    	for (int j = 1; j <= m; j++) {
    		for (int i = 1; i <= n; i++) {
    			f[i][j] = f[i][j - 1] * i;
    			if (j >= b) {
    				f[i][j] -= f[i - 1][j - b] * i * comb(j - 1, b - 1);
    			}
    		}
    	}
    }
    void work_g(int n) {
    	int m = n * (b - 1) + a;
    	for (int i = 0; i <= n; i++) {
    		g[i][0] = 1;
    	}
    	for (int j = 1; j <= m; j++) {
    		for (int i = 0; i <= n; i++) {
    			g[i][j] = g[i][j - 1] * (i + 1);
    			if (j >= a) {
    				g[i][j] -= f[i][j - a] * comb(j - 1, a - 1);
    			}
    			if (j >= b && i) {
    				g[i][j] -= g[i - 1][j - b] * i * comb(j - 1, b - 1);
    			}
    		}
    	}
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	cin >> n >> a >> b;
    	m = n * b;
    	if (n == 1) {
    		cout << 0 << '
    ';
    		return 0;
    	}
    	prepare(n * a);
    	Zi invn = ~Zi(n);
    	Zi ans = 0;
    
    	// last is 1
    	Zi p = 0;
    	work_f(n - 1);
    	for (int i = 0; i < n; i++) {
    		Zi tmp = 0;
    		Zi v = ~Zi(i + 1), pv = qpow(v, b);
    		for (int s = 0, _ = i * (b - 1); s <= _; s++, pv = pv * v) {
    			int rs = s + b - 1;
    			tmp += f[i][s] * pv * comb(rs, s);
    		}
    		tmp *= comb(n - 1, i);
    		if (i & 1) {
    			p -= tmp;
    		} else {
    			p += tmp;
    		}
    	}
    	ans += p;
    
    	// last is 2
    	p = 0;
    	work_g(n - 2);
    	for (int i = 0; i < n - 1; i++) {
    		Zi tmp = 0;
    		Zi v = ~Zi(i + 2), pv = qpow(v, b + b);
    		for (int s = b, _ = i * (b - 1) + a; s <= _; s++, pv *= v) {
    			int rs = s + b - 1;
    			tmp += (g[i][s] - f[i + 1][s]) * pv * fac[rs] * _fac[b - 1] * _fac[s];
    		}
    		tmp *= comb(n - 2, i);
    		if (i & 1) {
    			p -= tmp;
    		} else {
    			p += tmp;
    		}
    	}
    	ans += p * (n - 1);
    	ans = Zi(n) - ans * n;
    	printf("%d
    ", ans.v);
    	return 0;
    }

    Problem C 前进四

      考虑从大到小枚举位置,维护每个时间的后缀 min。

      这是一个区间取 min 操作。 segment tree beats 维护即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    template <typename T>
    boolean vmin(T& a, T b) {
    	return (a > b) ? (a = b, true) : (false);
    }
    template <typename T>
    boolean vmax(T& a, T b) {
    	return (a < b) ? (a = b, true) : (false);
    }
    
    template <typename T>
    T smax(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smax(T a, const K &...args) {
    	return max(a, smax(args...));
    }
    
    template <typename T>
    T smin(T x) {
    	return x;
    }
    template <typename T, typename ...K>
    T smin(T a, const K &...args) {
    	return min(a, smin(args...));
    }
    
    // debugging lib
    
    #define VN(x) #x
    #define Vmsg(x) VN(x) << " = " << (x)
    #define printv(x) cerr << VN(x) << " = " << (x);
    #define debug(...) fprintf(stderr, __VA_ARGS__);
    
    template <typename A, typename B>
    ostream& operator << (ostream& os, const pair<A, B>& z) {
    	os << "(" << z.first << ", " << z.second << ')';
    	return os;
    }
    template <typename T>
    ostream& operator << (ostream& os, const vector<T>& a) {
    	boolean isfirst = true;
    	os << "{";
    	for (auto z : a) {
    		if (!isfirst) {
    			os << ", ";
    		}
    		os << z;
    		isfirst = false;
    	}
    	os << '}';
    	return os;
    }
    
    #define pii pair<int, int>
    #define pil pair<int, ll>
    #define pli pair<ll, int>
    #define ll long long
    #define ull unsigned long long
    
    const int inf = (signed) (~0u >> 2);
    const ll llf = (signed ll) (~0ull >> 2);
    
    #define pb push_back
    #define eb emplace_back
    #define fi first
    #define sc second
    
    template <typename T>
    int vsize(vector<T>& x) {
    	return (signed) x.size(); 
    }
    
    template <typename T>
    int discrete(T* a, int* b, int n) {
        vector<T> v(a + 1, a + n + 1);
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
    	for (int i = 1; i <= n; i++) b[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    	return v.size();
    }
    
    mt19937 rng (time(NULL));
    
    int randint(int l, int r) {
    	return rng() % (r - l + 1) + l;
    }
    
    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    typedef class Input {
    	protected:
    		const static int limit = 65536;
    		FILE* file; 
    
    		int ss, st;
    		char buf[limit];
    	public:
    		
    		Input() : file(NULL)	{	};
    		Input(FILE* file) : file(file) {	}
    
    		void open(FILE *file) {
    			this->file = file;
    		}
    
    		void open(const char* filename) {
    			file = fopen(filename, "r");
    		}
    
    		char pick() {
    			if (ss == st)
    				st = fread(buf, 1, limit, file), ss = 0;//, cerr << "str: " << buf << "ed " << st << endl;
    			return buf[ss++];
    		}
    } Input;
    
    #define digit(_x) ((_x) >= '0' && (_x) <= '9')
    
    Input& operator >> (Input& in, unsigned& u) {
    	char x;
    	while (~(x = in.pick()) && !digit(x));
    	for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
    	return in;
    }
    
    Input& operator >> (Input& in, unsigned long long& u) {
    	char x;
    	while (~(x = in.pick()) && !digit(x));
    	for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
    	return in;
    }
    
    Input& operator >> (Input& in, int& u) {
    	char x;
    	while (~(x = in.pick()) && !digit(x) && x != '-');
    	int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
    	for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
    	u *= aflag;
    	return in;
    }
    
    Input& operator >> (Input& in, long long& u) {
    	char x;
    	while (~(x = in.pick()) && !digit(x) && x != '-');
    	int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
    	for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
    	u *= aflag;
    	return in;
    }
    
    Input& operator >> (Input& in, double& u) {
    	char x;
    	while (~(x = in.pick()) && !digit(x) && x != '-');
    	int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
    	for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
    	if (x == '.') {
    		double dec = 1;
    		for ( ; ~(x = in.pick()) && digit(x); u = u + (dec *= 0.1) * (x - '0'));
    	}
    	u *= aflag;
    	return in;
    }
    
    Input& operator >> (Input& in, char* str) {
    	char x;
    	while (~(x = in.pick()) && x != '
    ' && x != ' ')
    		*(str++) = x;
    	*str = 0;
    	return in;
    }
    
    Input in (stdin);
    
    typedef class Output {
    	protected:
    		const static int Limit = 65536;
    		char *tp, *ed;
    		char buf[Limit];
    		FILE* file;
    		int precision;
    
    		void flush() {
    			fwrite(buf, 1, tp - buf, file);
    			fflush(file);
    			tp = buf;
    		}
    
    	public:
    
    		Output() {	}
    		Output(FILE* file) : tp(buf), ed(buf + Limit), file(file), precision(6) {	}
    		Output(const char *str) : tp(buf), ed(buf + Limit), precision(6) {
    			file = fopen(str, "w");
    		}
    		~Output() {
    			flush();
    		}
    
    		void put(char x) {
    			if (tp == ed)
    				flush();
    			*(tp++) = x;
    		}
    
    		int get_precision() {
    			return precision;
    		}
    		void set_percision(int x) {
    			precision = x;
    		}
    } Output;
    
    Output& operator << (Output& out, int x) {
    	static char buf[35];
    	static char * const lim = buf + 34;
    	if (!x)
    		out.put('0');
    	else {
    		if (x < 0)
    			out.put('-'), x = -x;
    		char *tp = lim;
    		for ( ; x; *(--tp) = x % 10, x /= 10);
    		for ( ; tp != lim; out.put(*(tp++) + '0'));
    	}
    	return out;
    }
    
    Output& operator << (Output& out, long long x) {
    	static char buf[36];
    	static char * const lim = buf + 34;
    	if (!x)
    		out.put('0');
    	else {
    		if (x < 0)
    			out.put('-'), x = -x;
    		char *tp = lim;
    		for ( ; x; *(--tp) = x % 10, x /= 10);
    		for ( ; tp != lim; out.put(*(tp++) + '0'));
    	}
    	return out;
    }
    
    Output& operator << (Output& out, unsigned x) {
    	static char buf[35];
    	static char * const lim = buf + 34;
    	if (!x)
    		out.put('0');
    	else {
    		char *tp = lim;
    		for ( ; x; *(--tp) = x % 10, x /= 10);
    		for ( ; tp != lim; out.put(*(tp++) + '0'));
    	}
    	return out;
    }
    
    Output& operator << (Output& out, char x)  {
    	out.put(x);
    	return out;
    }
    
    Output& operator << (Output& out, const char* str) {
    	for ( ; *str; out.put(*(str++)));
    	return out;
    }
    
    Output& operator << (Output& out, double x) {
    	int y = x;
    	x -= y;
    	out << y << '.';
    	for (int i = out.get_precision(); i; i--, y = x * 10, x = x * 10 - y, out.put(y + '0'));
    	return out;
    }
    
    Output out (stdout);
    
    const int N = 1e6 + 5;
    
    typedef class SegTreeNode {
    	public:
    		int mx, mx2;
    		int tgm, tga;
    		SegTreeNode *l, *r;
    
    		void upd(int x, int y) {
    			if (x <= mx2) {
    				push_down();
    				l->upd(x, y);
    				r->upd(x, y);
    				push_up();
    			} else if (x < mx) {
    				assert(x < tgm);
    				tgm = x;
    				mx = x;
    				tga += y;
    			}
    		} 
    		void push_down() {
    			if (tga) {
    				l->upd(tgm, tga);
    				r->upd(tgm, tga);
    				tgm = inf, tga = 0;
    			}
    		}
    		void push_up() {
    			if (l->mx == r->mx) {
    				mx = l->mx;
    				mx2 = max(l->mx2, r->mx2);
    			} else if (l->mx > r->mx) {
    				mx = l->mx;
    				mx2 = max(l->mx2, r->mx);
    			} else {
    				mx = r->mx;
    				mx2 = max(l->mx, r->mx2);
    			}
    		}
    } SegTreeNode;
    
    typedef class SegmentTree {
    	public:
    		static SegTreeNode pool[N << 1];
    		static SegTreeNode* top;
    
    		static SegTreeNode* newnode() {
    			top->mx = -inf;
    			top->mx2 = -inf;
    			top->tgm = inf;
    			top->tga = 0;
    			return top++;
    		}
    		
    		int n;
    		SegTreeNode* rt;
    
    		SegmentTree() : rt(NULL) {	}
    		
    		void build(SegTreeNode*& p, int l, int r) {
    			p = newnode();
    			if (l ^ r) {
    				int mid = (l + r) >> 1;
    				build(p->l, l, mid);
    				build(p->r, mid + 1, r);
    				p->push_up();
    			} else {
    				p->mx = inf;
    			}
    		}
    		void build(int n) {
    			this->n = n;
    			build(rt, 0, n);
    		}
    
    		int query(SegTreeNode* p, int l, int r, int idx) {
    			if (l == r) {
    				return p->tga;
    			}
    			p->push_down();
    			int mid = (l + r) >> 1;
    			if (idx <= mid)
    				return query(p->l, l, mid, idx);
    			return query(p->r, mid + 1, r, idx);
    		}
    
    		void modify(SegTreeNode* p, int l, int r, int ql, int qr, int v) {
    			if (v >= p->mx) {
    				return;
    			}
    			if (l == ql && r == qr) {
    				p->upd(v, 1);
    				return;
    			}
    			p->push_down();
    			int mid = (l + r) >> 1;
    			if (qr <= mid) { 
    				modify(p->l, l, mid, ql, qr, v);
    			} else if (ql > mid) {
    				modify(p->r, mid + 1, r, ql, qr, v);
    			} else {
    				modify(p->l, l, mid, ql, mid, v);
    				modify(p->r, mid + 1, r, mid + 1, qr, v);
    			}
    			p->push_up();
    		}
    
    		int query(int idx) {
    			return query(rt, 0, n, idx);
    		}
    		void modify(int l, int r, int v) {
    			return modify(rt, 0, n, l, r, v);
    		}
    } SegmentTree;
    
    SegTreeNode SegmentTree :: pool[N << 1];
    SegTreeNode* SegmentTree :: top = SegmentTree :: pool;
    
    typedef class Event {
    	public:
    		int op, p, t, v, tog;
    
    		Event(int op, int p, int t, int v, int tog) : op(op), p(p), t(t), v(v), tog(tog) {	}
    
    		bool operator < (Event b) const {
    			if (p ^ b.p) {
    				return p > b.p;
    			}
    			if (op ^ b.op) {
    				return op < b.op;
    			}
    			if (t ^ b.t) {
    				return t > b.t;
    			}
    			return tog > b.tog;
    		}
    } Event;
    	
    int n, m;
    int ans[N];
    vector<Event> E;
    SegmentTree st;
    
    int main() {
    	in >> n >> m;
    	for (int i = 1, x; i <= n; i++) {
    		in >> x;
    		E.emplace_back(1, i, 0, x, 0);
    	}
    	int qt = 0;
    	for (int i = 1, op, x, y; i <= m; i++) {
    		in >> op >> x;
    		if (op == 1) {
    			in >> y;
    			E.emplace_back(1, x, qt, y, i);
    		} else {
    			E.emplace_back(2, x, qt++, 0, i);
    		}
    	}
    	st.build(qt);
    	sort(E.begin(), E.end());
    	auto it = E.begin(), _it = E.end();
    	for (int i = n, ls; i; i--) {
    		ls = qt + 1;
    		while (it != _it && (*it).p == i) {
    			auto& e = *it;
    			if (e.op == 1) {
    				if (e.t ^ ls) {
    					st.modify(e.t, ls - 1, e.v);
    					ls = e.t;
    				}
    			} else {
    				ans[e.t] = st.query(e.t);
    			}
    			it++;
    		}
    	}
    	for (int i = 0; i < qt; i++) {
    		if (~ans[i]) { 
    			out << ans[i] << '
    ';
    		}
    	}
    	return 0;
    }

  • 相关阅读:
    编程中Visual Studio常用的快捷键
    解决博易博客后台文章管理页面无法显示分页的问题
    iReaper for WP7 顺利完工
    Visual Studio中web应用程序和网站区别
    SQL批处理
    SQL安全性
    实习之路之篇
    python 日志文件
    后端调用python遥感功能的方式
    C#使用系统的“显示桌面”功能(Shell.Application)
  • 原文地址:https://www.cnblogs.com/yyf0309/p/ur19.html
Copyright © 2011-2022 走看看