• 2019杭电多校第三场


    2019杭电多校第三场

    1002. Blow up the city

    upsloved

    有一个DAG,出度为(0)的点是指挥中心,(q)次询问,每次给出两个点,这两个点存有关键物资,你可以炸掉一个点和它的邻接边,使得这两个点中任意一个点的物资不能到达指挥中心(有一个点不能到达任意一个指挥中心即可),求方案数,询问独立

    并不会支配树,比赛的时候想到了这个东西的概念,但是不会实现,赛后学习一波

    把图反过了,建一个额外的起点指向指挥中心,求出支配树,每次询问u,v就只要计算u,v以及它们的LCA的深度就好了

    #include <bits/stdc++.h>
    using LL = long long;
    using namespace std;
    
    const int N = 200010;
    struct Node{int to,next;};
    int T, n, m, q, u, v, dfn[N], clo, rev[N], f[N], semi[N], idom[N], deg[N], dep[N], fa[N][18];
    
    struct Graph{
    	Node E[N << 1]; int head[N], tot;
    	inline void clear(){
    		tot = 0;
    		for(int i = 0; i <= n; ++i) head[i] = -1;
    	}
    	inline void link(int u, int v){
    		E[tot] = (Node){v, head[u]}; head[u] = tot++;
    	}
    }pre, nxt, dom;
    
    struct uset{
    	int fa[N], Mi[N];
    	inline void init(){
    		for(int i = 1; i <= n; ++i)
    			fa[i] = Mi[i] = semi[i] = i;
    	}
    	inline int find(int x){
    		if(fa[x] == x) return x;
    		int fx = fa[x], y = find(fa[x]);
    		if(dfn[semi[Mi[fx]]] < dfn[semi[Mi[x]]]) Mi[x] = Mi[fx];
    		return fa[x] = y;
    	}
    }uset;
    
    inline void tarjan(int x) {
    	dfn[x] = ++clo; rev[clo] = x;
    	for(int e = nxt.head[x]; ~e; e = nxt.E[e].next){
    		if(!dfn[nxt.E[e].to])
    			f[nxt.E[e].to] = x, tarjan(nxt.E[e].to);
    	}
    }
    
    inline void dfs(int x, int pre, int depth) {
    	dep[x] = depth;
    	fa[x][0] = pre;
    	for(int i = 1; i < 18; ++i)
    		fa[x][i] = fa[fa[x][i - 1]][i - 1];
    	for(int e = dom.head[x]; ~e; e = dom.E[e].next)
    		dfs(dom.E[e].to, x, depth + 1);
    }
    
    inline int LCA(int u, int v) {
    	if(dep[u] < dep[v]) swap(u, v);
    	for(int i = 17; ~i; --i) {
    		if(dep[fa[u][i]] >= dep[v])
    			u = fa[u][i];
    	}
    	if(u == v) return u;
    	for(int i = 17; ~i; --i) {
    		if(fa[u][i] != fa[v][i])
    			u = fa[u][i], v = fa[v][i];
    	}
    	return fa[u][0];
    }
    
    inline void calc(){
    	for(int i = n; i >= 2; --i){
    		int y = rev[i], tmp = n;
    		for(int e = pre.head[y]; ~e; e = pre.E[e].next){
    			int x = pre.E[e].to; if(!dfn[x]) continue;
    			if(dfn[x] < dfn[y]) tmp = min(tmp, dfn[x]);
    			else uset.find(x), tmp = min(tmp, dfn[semi[uset.Mi[x]]]);
    		}
    		semi[y] = rev[tmp]; uset.fa[y] = f[y];
    		dom.link(semi[y], y);
    		y = rev[i - 1];
    		for(int e = dom.head[y]; ~e; e = dom.E[e].next){
    			int x = dom.E[e].to; uset.find(x);
    			if(semi[uset.Mi[x]] == y) idom[x] = y;
    			else idom[x] = uset.Mi[x];
    		}
    	}
    	for(int i = 2; i <= n; ++i){
    		int x = rev[i];
    		if(idom[x] != semi[x])
    			idom[x] = idom[idom[x]];
    	}
    	dom.clear();
    	for(int i = 1; i < n; ++i)
    		dom.link(idom[i], i);
    	dfs(n, 0, 0);
    }
    
    int main() {
    	scanf("%d", &T);
    	while(T--) {
    		scanf("%d%d", &n, &m);
    		clo = 0; n++; dep[0] = -1;
    		for(int i = 1; i <= n; ++i)
    			deg[i] = dfn[i] = rev[i] = semi[i] = idom[i] = f[i] = 0;
    		pre.clear(); nxt.clear(); dom.clear(); uset.init();
    		for(int i = 1; i <= m; ++i){
    			scanf("%d%d", &u, &v);
    			pre.link(u, v);
    			nxt.link(v, u);
    			deg[u]++;
    		}
    		for(int i = 1; i < n; ++i) {
    			if(deg[i] == 0) {
    				nxt.link(n, i);
    				pre.link(i, n);
    			}
    		}
    		tarjan(n);
    		calc();
    		scanf("%d", &q);
    		while(q--) {
    			scanf("%d%d", &u, &v);
    			printf("%d
    ", dep[u] + dep[v] - dep[LCA(u, v)]);
    		}
    	}
    	return 0;
    }
    

    1004. Distribution of books

    upsloved

    有一个长为(n)的数列(A), 你需要将找(k)个飞空不相交区间,这些区间并起来是(A)的一个前缀区间,使得这(k)个区间每个区间的和的最大值最小

    二分答案,线段树优化dp套路,代码不放了

    1006. Fansblog

    solved at 00:54

    队友做的,素数分布,威尔逊定理,int128

    1007. Find the answer

    solved at 01:24(+3)

    离散化之后线段树维护区间和以及区间数的个数

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 2e5 + 10;
    
    struct node {
    	int val, id;
    	bool operator<(const node &rhs) const {
    		return val < rhs.val;
    	}
    }a[N];
    
    int rnk[N], T, n, ans[N], m, sum, mn, b[N];
    
    long long tree[N << 2];
    int cnt[N << 2];
    
    void pushup(int rt) {
    	tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
    	cnt[rt] = cnt[rt << 1] + cnt[rt << 1 | 1];
    }
    
    void build(int rt, int l, int r) {
    	tree[rt] = 0; cnt[rt] = 0;
    	if(l == r) return;
    	int mid = l + r >> 1;
    	build(rt << 1, l, mid);
    	build(rt << 1 | 1, mid + 1, r);
    }
    
    void update(int rt, int l, int r, int pos, int val) {
    	if(l == r) {tree[rt] += val, cnt[rt]++; return;}
    	int mid = l + r >> 1;
    	if(pos <= mid) update(rt << 1, l, mid, pos, val);
    	else update(rt << 1 | 1, mid + 1, r, pos, val);
    	pushup(rt);
    }
    
    int query(int rt, int l, int r, long long val) {
    	if(l == r) return tree[rt] <= val ? cnt[rt] : 0;
    	int mid = l + r >> 1;
    	if(tree[rt << 1] <= val) return cnt[rt << 1] + query(rt << 1 | 1, mid + 1, r, val - tree[rt << 1]);
    	else return query(rt << 1, l, mid, val); 
    }
    
    int main() {
    	read(T);
    	while(T--) {
    		sum = ans[0] = 0;
    		read(n); read(m);
    		for(int i = 1; i <= n; ++i) {
    			read(a[i].val);
    			b[i] = a[i].val;
    			a[i].id = i;
    		}
    		sort(a + 1, a + n + 1);
    		for(int i = 1; i <= n; ++i)
    			rnk[a[i].id] = i;
    		build(1, 1, n);
    		for(int i = 1; i <= n; ++i) {
    			ans[i] = i - 1 - query(1, 1, n, m - b[i]);
    			update(1, 1, n, rnk[i], b[i]);
    		}
    		for(int i = 1; i <= n; ++i)
    			printf("%d ", ans[i]);
    		puts("");
    	}
    	return 0;
    }
    
    
    

    1009. K subsequence

    solved at 04:42(+14)

    有一个长为(n)的数列,你需要找出(k)个不相交的非降子序列使得选出的数和最大(1<=n<=2000, 1<=k<=10)

    最小费用最大流经典题,拆点建图,每个点(i)拆成(i_1)(i_2)(i_1)(i_2)建容量为(1),费用为(-a_i)的边,(s)(i_1)建容量为(1),费用为(0)的边,(i_2)(t)建容量为(1),费用为(0)的边,如果(a[i]<=a[j])(i<j)(i_2)(j_1)建容量为(1),费用为(0)的边,最后(ss)(s)建容量为(k),费用为(0)的边,(ss)(t)(MCMF),最小费用取相反数就是答案

    1011. Squrirrel

    树型dp,待补

  • 相关阅读:
    mysql配置完半同步复制之后报错[ERROR] The server quit without updating PID file
    mysql配置为半同步复制
    mysql主从复制(半同步方式)
    ssh连接时提示THE AUTHENTICITY OF HOST XX CAN’T BE ESTABLISHED
    Linux 记录所有用户登录和操作的详细日志
    如何禁止某个linux用户访问某些文件夹及执行某些命令
    怎样把linux客户端用户禁止用 su命令来切换用户
    Django---进阶10
    Django---入门
    Django---进阶1
  • 原文地址:https://www.cnblogs.com/tusikalanse/p/11273174.html
Copyright © 2020-2023  润新知