zoukankan      html  css  js  c++  java
  • 【BZOJ 3083】遥远的国度

    这道题很简单的连剖+分类讨论,但是SDOI Round2要来了,不会手动栈怎么办呢?只好用一下这道题练习一下手动栈了,结果调了一天多QwQ

    链剖的第一个dfs用bfs水过就行,但是我自以为是地把倍增写错了,坑了好久啊QAQ

    这道题因为要询问子树,连剖的第二个dfs就不能再用bfs水过了,只能强行手动栈。

    一开始拍小数据拍出了好多错,改过来后拍了无数组极限数据也拍不出来,因为构造的极限数据太弱了(偷懒构造u<v)根本无法暴露倍增的漏洞啊!!!

    手残错误毁一生,写代码时不要自以为是。希望SD省选能够给我们一个更好的编程环境和评测环境(NOILinux恐怕是奢望吧)

    #include<stack>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 100003;
    const int inf = 0x7fffffff;
    void read(int &k) {
    	k = 0; int fh = 1; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar())
    		if (c == '-') fh = -1;
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = (k << 1) + (k << 3) + c - '0';
    	k = k * fh;
    }
    
    struct node {int nxt, to;} E[N << 1];
    int n, m, point[N], cnt = 0, pos[N], wt[N], deep[N];
    int lazy[N * 8], mn[N * 8], top[N], sz[N], f[N][18], root, a[N], son[N];
    
    void ins(int x, int y) {E[++cnt] = (node) {point[x], y}; point[x] = cnt;}
    stack <int> S;
    int qu[N];
    void _() {
    	int p = 0, q = 1; qu[1] = 1;
    	while (p != q) {
    		int u = qu[++p];
    		for(int tmp = point[u]; tmp; tmp = E[tmp].nxt)
    			if (E[tmp].to != f[u][0])
    				f[E[tmp].to][0] = u, deep[E[tmp].to] = deep[u] + 1, qu[++q] = E[tmp].to;
    	}
    	for(int i = q; i >= 1; --i) {
    		int u = qu[i], fa = f[u][0];
    		++sz[u];
    		sz[fa] += sz[u];
    		if (sz[u] > sz[son[fa]]) son[fa] = u;
    	}
    	for(int j = 1; j <= 17; ++j)
    		for(int i = 1; i <= n; ++i)
    			f[i][j] = f[f[i][j - 1]][j - 1];
    }
    void __() {
    	top[1] = 1; cnt = 0;
    	S.push(1);
    	while (!S.empty()) {
    		int u = S.top(); S.pop();
    		pos[++cnt] = u; wt[u] = cnt;
    		for(int tmp = point[u]; tmp; tmp = E[tmp].nxt)
    			if (E[tmp].to != f[u][0] && E[tmp].to != son[u])
    				top[E[tmp].to] = E[tmp].to, S.push(E[tmp].to);
    		if (son[u]) {top[son[u]] = top[u]; S.push(son[u]);}
    	}
    }
    /* 下面是正确的人工栈模板,完美模拟dfs,但是我学会它不到5小时我就用bfs把它淘汰了 
    void _() {
    	S.push(Data(1, point[1]));
    	sz[1] = 1;
    	while (!S.empty()) {
    		int x = S.top().x, y = S.top().y; S.pop();
    		if (y) {
    			S.push(Data(x, E[y].nxt));
    			int v = E[y].to;
    			if (v != f[x][0]) {
    				f[v][0] = x;
    				sz[v] = 1;
    				deep[v] = deep[x] + 1;
    				for(int i = 1; i <= 17; ++i) {f[v][i] = f[f[v][i - 1]][i - 1]; if (f[v][i] == 0) break;}
    				S.push(Data(v, point[v]));
    			}
    		} else {
    			if (!S.empty()) {
    				sz[S.top().x] += sz[x];
    				if (sz[x] > sz[son[S.top().x]]) son[S.top().x] = x;
    			}
    		}
    	}
    }*/
    
    void pushdown(int rt) {
    	if (lazy[rt]) {
    		mn[rt << 1] = mn[rt << 1 | 1] = lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];
    		lazy[rt] = 0;
    	}
    }
    void pushup(int rt) {mn[rt] = min(mn[rt << 1], mn[rt << 1 | 1]);}
    void Build(int rt, int l, int r) {
    	if (l == r) {mn[rt] = a[pos[l]]; mn[rt << 1] = mn[rt << 1 | 1] = inf; return;}
    	int mid = (l + r) >> 1;
    	Build(rt << 1, l, mid);
    	Build(rt << 1 | 1, mid + 1, r);
    	pushup(rt);
    }
    void add(int rt, int l, int r, int L, int R, int x) {
    	if (L <= l && r <= R) {lazy[rt] = x; mn[rt] = x; return;}
    	int mid = (l + r) >> 1;
    	pushdown(rt);
    	if (L <= mid) add(rt << 1, l, mid, L, R, x);
    	if (R > mid) add(rt << 1 | 1, mid + 1, r, L, R, x);
    	pushup(rt);
    }
    void Add(int x, int y, int z) {
    	for(; top[x] != top[y]; x = f[top[x]][0]) {
    		if (deep[top[x]] < deep[top[y]]) swap(x, y);
    		add(1, 1, n, wt[top[x]], wt[x], z);
    	}
    	if (deep[x] < deep[y]) swap(x, y);
    	add(1, 1, n, wt[y], wt[x], z);
    }
    int QQ(int rt, int l, int r, int L, int R) {
    	if (L <= l && r <= R) return mn[rt];
    	int mid = (l + r) >> 1, s = inf;
    	pushdown(rt);
    	if (L <= mid) s = min(s, QQ(rt << 1, l, mid, L, R));
    	if (R > mid) s = min(s, QQ(rt << 1 | 1, mid + 1, r, L, R));
    	return s;
    }
    int Q(int L, int R) {
    	if (L > n || R < 1 || L > R) return inf;
    	return QQ(1, 1, n, L, R);
    }
    
    int lower;
    int LCA(int x, int y) {
    	if (deep[x] < deep[y]) return 1;
    	for(int i = 16; i >= 0; --i) if (deep[f[x][i]] > deep[y]) x = f[x][i];
    	lower = x;
    	return f[x][0] != y;
    }
    
    int main() {
    	read(n); read(m);
    	int u, v, op, x;
    	for(int i = 1; i < n; ++i) {
    		read(u); read(v);
    		ins(u, v); ins(v, u);
    	}
    	
    	_();
    	__();
    	
    	for(int i = 1; i <= n; ++i) read(a[i]);
    	
    	Build(1, 1, n);
    	
    	read(root);
    	for(int i = 1; i <= m; ++i) {
    		read(op);
    		switch (op) {
    			case 1:
    				read(root);
    			break;
    			case 2:
    				read(u); read(v); read(x);
    				Add(u, v, x);
    			break;
    			case 3:
    				read(u);
    				if (root == u)
    					printf("%d
    ", Q(1, n));
    				else
    					if (LCA(root, u)) {
    						printf("%d
    ", Q(wt[u], wt[u] + sz[u] - 1));
    					} else {
    						v = min(Q(1, wt[lower] - 1), Q(wt[lower] + sz[lower], n));
    						printf("%d
    ", v);
    					}
    			break;
    		}
    	}
    	
    	return 0;
    }
    

    注释掉了能够完美模拟dfs但并没有什么用的手动栈= =

  • 相关阅读:
    onSaveInstanceState和onRestoreInstanceState()
    Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性
    又优化了一下 Android ListView 异步加载图片
    ListView异步加载图片
    SpannableString 设置一段文字中部分字体颜色
    Android Studio apk 打包流程
    svn分支开发与主干合并(branch & merge)
    SVN使用教程之——分支、合并
    XMPP协议实现原理介绍
    监听器
  • 原文地址:https://www.cnblogs.com/abclzr/p/5484373.html
Copyright © 2011-2022 走看看