zoukankan      html  css  js  c++  java
  • Codeforces 901C Bipartite Segments

    题目蓝链

    Solution

    因为这是一个仙人掌图,所以我们可以通过(tarjan)缩点双找出图中所有的简单环。然后我们找出每一个环中的最大编号和最小编号,并按最大编号从小到大排序。然后我们把询问离线下来,并且挂在询问的右端点处

    然后我们从左往右扫,处理每一个节点处的询问之前,先把最左能走的不会形成环的位置更新出来。然后用线段树把这一段区间加(1)

    询问就直接再线段树上区间求和就行了

    还有一种做法,就是直接预处理出每一个点最左能走的不会形成环的位置,记为(pos[i])。对于查询([l, r]),二分找到最小的(i)使得(pos[i] > l)。然后我们分别对([l, i - 1])([i, r])计算贡献,加起来就可以了

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define fst first
    #define snd second
    #define squ(x) ((LL)(x) * (x))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    typedef long long LL;
    typedef pair<int, int> pii;
    
    inline int read() {
    	int sum = 0, fg = 1; char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
    	for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
    	return fg * sum;
    }
    
    const int maxn = 3e5 + 10;
    
    vector<int> g[maxn];
    vector<pii> v[maxn];
    
    int d[maxn], low[maxn], pre[maxn], dfn;
    int S[maxn], top, cnt, n, m, q;
    
    pii p[maxn];
    LL ans[maxn];
    
    void tarjan(int now, int f) {
    	d[now] = low[now] = ++dfn;
    	S[++top] = now;
    	for (int i = 0; i < g[now].size(); i++) {
    		int son = g[now][i];
    		if (son == f) continue;
    		if (!d[son]) {
    			tarjan(son, now);
    			low[now] = min(low[now], low[son]);
    			if (low[son] >= d[now]) {
    				int Max = 0, Min = n + 1, tot = 0;
    				while (top) {
    					int x = S[top--];
    					Max = max(Max, x);
    					Min = min(Min, x);
    					++tot;
    					if (x == son) break;
    				}
    				Max = max(Max, now), Min = min(Min, now);
    				if (tot > 1) p[++cnt] = (pii){Max, Min};
    			}
    		}else low[now] = min(low[now], d[son]);
    	}
    }
    
    namespace ST {
    
    	LL A[maxn << 2], tag[maxn << 2];
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    
    	void push_up(int rt) { A[rt] = A[ls] + A[rs]; }
    
    	void push_down(int rt, int l, int r) {
    		if (!tag[rt]) return;
    		int mid = (l + r) >> 1;
    		tag[ls] += tag[rt];
    		tag[rs] += tag[rt];
    		A[ls] += tag[rt] * (mid - l + 1);
    		A[rs] += tag[rt] * (r - mid);
    		tag[rt] = 0;
    	}
    
    	void change(int rt, int l, int r, int L, int R) {
    		if (L <= l && r <= R) {
    			A[rt] += r - l + 1, ++tag[rt]; return;
    		}
    		push_down(rt, l, r);
    		int mid = (l + r) >> 1;
    		if (L <= mid) change(ls, l, mid, L, R);
    		if (R > mid) change(rs, mid + 1, r, L, R);
    		push_up(rt);
    	}
    
    	LL query(int rt, int l, int r, int L, int R) {
    		if (L <= l && r <= R) return A[rt];
    		push_down(rt, l, r);
    		int mid = (l + r) >> 1; LL res = 0;
    		if (L <= mid) res += query(ls, l, mid, L, R);
    		if (R > mid) res += query(rs, mid + 1, r, L, R);
    		return res;
    	}
    
    }
    
    int main() {
    #ifdef xunzhen
    	freopen("graph.in", "r", stdin);
    	freopen("graph.out", "w", stdout);
    #endif
    
    	n = read(), m = read();
    	for (int i = 1; i <= m; i++) {
    		int x = read(), y = read();
    		g[x].push_back(y);
    		g[y].push_back(x);
    	}
    
    	q = read();
    	for (int i = 1; i <= q; i++) {
    		int x = read(), y = read();
    		v[y].push_back((pii){x, i});
    	}
    
    	for (int i = 1; i <= n; i++) if (!d[i]) tarjan(i, 0);
    
    	sort(p + 1, p + cnt + 1);
    	int j = 1, Max = 0;
    	for (int i = 1; i <= n; i++) {
    		while (j <= cnt && p[j].fst <= i) Max = max(Max, p[j++].snd);
    		ST::change(1, 1, n, Max + 1, i);
    		for (int j = 0; j < v[i].size(); j++)
    			ans[v[i][j].snd] = ST::query(1, 1, n, v[i][j].fst, i);
    	}
    
    	for (int i = 1; i <= q; i++) printf("%lld
    ", ans[i]);
    
    	return 0;
    }
    

    Summary

    考试的时候没有注意到这是一个仙人掌,以为这是一个仙人球,然后我就打了一个缩边双...

  • 相关阅读:
    T-sql for xml path使用
    解决 SQL Server2012附加出错的问题
    安装应用程序 报“ 997 重叠 I/O 操作在进行中”错解决办法
    使用QQ互联登录应用
    monogdb windows环境下 安装及使用简单示例
    idle-实现清屏
    colorscheme-如何vim颜色风格
    android-从官网下拉源码(ubuntu)
    hq-源码编译
    文件目录进入终端
  • 原文地址:https://www.cnblogs.com/xunzhen/p/9811130.html
Copyright © 2011-2022 走看看