Bipartite Segments

因为图中只存在奇数长度的环, 所以它是个只有奇数环的仙人掌, 每条边只属于一个环。

那么我们能把所有环给扣出来, 所以我们询问的区间不能包含每个环里的最大值和最小值,

这个东西能用dfs直接扣, 找最大值和最小值能用倍增, 或者直接tarjan扣出来就好。 然后

我们可以处理出每个点开始往右延伸的最大位置, 求答案能离线线段树(我是这么写的),

但有一点就是这个数组是个单调的数组, 所以我们能二分出那个刚好超过R的位置, 直接求就好啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long using namespace std; const int N = 3e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-;
const double PI = acos(-); int n, m, q, to[N], f[N][], mx[N][], mn[N][], depth[N];
bool vis[N];
LL ans[N];
vector<int> G[N];
vector<PII> qus[N]; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
LL a[N << ], lazy[N << ];
inline void pull(int rt) {
a[rt] = a[rt << ] + a[rt << | ];
}
inline void push(int rt, int l, int mid, int r) {
if(lazy[rt]) {
a[rt << ] += lazy[rt] * (mid - l + );
a[rt << | ] += lazy[rt] * (r - mid);
lazy[rt << ] += lazy[rt];
lazy[rt << | ] += lazy[rt];
lazy[rt] = ;
}
}
void update(int L, int R, LL val, int l, int r, int rt) {
if(l >= L && r <= R) {
a[rt] += val * (r - l + );
lazy[rt] += val;
return;
}
int mid = l + r >> ;
push(rt, l, mid, r);
if(L <= mid) update(L, R, val, lson);
if(R > mid) update(L, R, val, rson);
pull(rt);
}
LL query(int L, int R, int l, int r, int rt) {
if(l >= L && r <= R) return a[rt];
int mid = l + r >> ;
push(rt, l, mid, r);
if(R <= mid) return query(L, R, lson);
else if(L > mid) return query(L, R, rson);
else return query(L, R, lson) + query(L, R, rson);
} void dfs(int u, int fa) {
vis[u] = true;
depth[u] = depth[fa] + ;
f[u][] = fa;
mx[u][] = u, mn[u][] = u;
for(int i = ; i < ; i++) {
f[u][i] = f[f[u][i - ]][i - ];
mx[u][i] = max(mx[u][i - ], mx[f[u][i - ]][i - ]);
mn[u][i] = min(mn[u][i - ], mn[f[u][i - ]][i - ]);
}
for(auto& v : G[u]) {
if(v == fa || vis[v]) continue;
dfs(v, u);
}
} void getVal(int u, int v) {
int MX = v, MN = v;
for(int i = ; i >= ; i--) {
if(depth[u] - depth[v] >= ( << i)) {
MX = max(MX, mx[u][i]);
MN = min(MN, mn[u][i]);
u = f[u][i];
}
}
to[MN] = MX - ;
} void getTo(int u, int fa) {
vis[u] = true;
for(auto& v : G[u]) {
if(v == fa) continue;
else if(!vis[v]) getTo(v, u);
else if(vis[v]) {
if(depth[u] > depth[v]) getVal(u, v);
}
}
} int main() {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) to[i] = n;
for(int i = ; i <= m; i++) {
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i = ; i <= n; i++)
if(!vis[i]) dfs(i, );
memset(vis, , sizeof(vis));
for(int i = ; i <= n; i++)
if(!vis[i]) getTo(i, );
for(int i = n - ; i >= ; i--)
to[i] = min(to[i], to[i + ]);
scanf("%d", &q);
for(int i = ; i <= q; i++) {
int L, R; scanf("%d%d", &L, &R);
qus[L].push_back(mk(R, i));
}
for(int i = n; i >= ; i--) {
update(i, to[i], , , n, );
for(auto& Q : qus[i]) ans[Q.se] = query(i, Q.fi, , n, );
}
for(int i = ; i <= q; i++) printf("%lld\n", ans[i]);
return ;
} /*
*/

Codeforces 901C Bipartite Segments的更多相关文章

  1. Codeforces 901C Bipartite Segments(Tarjan + 二分)

    题目链接  Bipartite Segments 题意  给出一个无偶环的图,现在有$q$个询问.求区间$[L, R]$中有多少个子区间$[l, r]$ 满足$L <= l <= r &l ...

  2. Codeforces 901C. Bipartite Segments(思维题)

    擦..没看见简单环..已经想的七七八八了,就差一步 显然我们只要知道一个点最远可以向后扩展到第几个点是二分图,我们就可以很容易地回答每一个询问了,但是怎么求出这个呢. 没有偶数简单环,相当于只有奇数简 ...

  3. Codeforces Round #453 (Div. 1) 901C C. Bipartite Segments

    题 http://codeforces.com/contest/901/problem/C codeforces 901C 解 首先因为图中没有偶数长度的环,所以: 1.图中的环长度全是奇数,也就是说 ...

  4. 【CodeForces】901 C. Bipartite Segments

    [题目]C. Bipartite Segments [题意]给定n个点m条边的无向连通图,保证不存在偶数长度的简单环.每次询问区间[l,r]中包含多少子区间[x,y]满足只保留[x,y]之间的点和边构 ...

  5. codeforces 895B XK Segments 二分 思维

    codeforces 895B XK Segments 题目大意: 寻找符合要求的\((i,j)\)对,有:\[a_i \le a_j \] 同时存在\(k\),且\(k\)能够被\(x\)整除,\( ...

  6. Bipartite Segments CodeForces - 901C (区间二分图计数)

    大意: 给定无向图, 无偶环, 每次询问求[l,r]区间内, 有多少子区间是二分图. 无偶环等价于奇环仙人掌森林, 可以直接tarjan求出所有环, 然后就可以预处理出每个点为右端点时的答案. 这样的 ...

  7. [离散化+树状数组]CodeForces - 652D Nested Segments

    Nested Segments time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  8. Codeforces 976C Nested Segments

    题面: 传送门 C. Nested Segments Input file: standard input Output file: standard output Time limit: 2 secon ...

  9. Codeforces 193D - Two Segments(线段树)

    Codeforces 题目传送门 & 洛谷题目传送门 感觉这个 *2900 并不难啊,为什么我没想出来呢 awa 顺便膜拜 ycx 一眼秒掉此题 %%% 首先碰到这类题有两种思路,一是枚举两个 ...

随机推荐

  1. Shell结合Expect实现自动输入密码

    Shell结合Expect自动输入密码示例 #!/bin/bash cd /data/live /usr/bin/expect <<-EOF spawn git clone "s ...

  2. Linux TCP 连接数

    查看 TCP 连接数 : 每一个 IP 访问的链接数:head 默认 前10 netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: '{print ...

  3. 组合框QGroupBox

    样式: 注意:内部必须使用布局控件 import sys from PyQt5.QtCore import Qt from PyQt5.QtGui import QPixmap from PyQt5. ...

  4. Go 语言读书笔记

    Go语言的设计理念很明确,就是将动态类型语言的编程容易度和静态类型语言的安全效率结合起来.     Go语言,又称Golang,是Google开发的一款静态强类型.编译型.并发型,并具有垃圾回收机制的 ...

  5. 文加图, 理解Http请求与响应

    1. http请求和响应步骤 在讲解OkHttp之前, 我们首先来个高清大图, 看下http请求的整个步骤, 有个整体概念.  2. http每一步详细内容 在一次完整的HTTP通信过程中, Web浏 ...

  6. slf4j的简单用法以及与log4j的区别

    之前在项目中用的日志记录器都是log4j的日志记录器,可是到了新公司发现都是slf4j,于是想着研究一下slf4j的用法. 注意:每次引入Logger的时候注意引入的jar包,因为有Logger的包太 ...

  7. 关于形如--error LNK2005: xxx 已经在 msvcrtd.lib ( MSVCR90D.dll ) 中定义--的问题分析解决

    转自:http://hi.baidu.com/qinfengxiaoyue/item/ff262ccfb53b4c2ba0b50a89 引自:http://blog.csdn.net/sptoor/a ...

  8. 使用python中的matplotlib 画图,show后关闭窗口,继续运行命令

    使用python中的matplotlib 画图,show后关闭窗口,继续运行命令 在用python中的matplotlib 画图时,show()函数总是要放在最后,且它阻止命令继续往下运行,直到1.0 ...

  9. [转] bss段、data段、text段

    1.前言 一个程序本质上都是由 BSS 段.DATA段.TEXT段三个组成的. 本文主要分编译时和运行时分别对 对data段 bss段 text段 堆 栈作一简要说明 2. 程序编译时概念说明 程序与 ...

  10. jvm系列二、JVM内存结构

    原文链接:http://www.cnblogs.com/ityouknow/p/5610232.html 所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemory ...