不想翻译了,直接放luogu翻译


说了没有偶环,也就是说全是奇环,再结合二分图性质,那么暴力的话,固定左端点,增大序号,加点直到产生环就不合法了。也就是说,任何一个环,只要他上面的数全都被加了,就不合法了,那么,环上的数若最大$\text{m2}$,最小$\text{m1}$,那么如果当前枚举的子区间$x\le m1且y\ge m2$,那就不合法了。这样,我们可以转化一下问题,给一堆区间,然后每次问$[L,R]$有多少子区间不合法(即存在一个给定的区间被这个子区间覆盖了),然后总方案数减去不合法数。但是还存在两个问题。

一,上述的环有多少个?怎么找?发现所有环都是奇环,任何两个奇环不能相交或者公用边,因为这些情况都会附带再产生一个偶环(结论源自于手动模拟),与题意矛盾。所以,每条边最多属于一个简单的奇环。那么,这就是一个仙人掌。。所以,可以证出,环是相互独立的,并且不会超过$M/3$个。这样,就可以接受了,这些环通过点连接,可以看成是一堆点双连接,我们直接tarjan找点双,每个点双对应到区间上即可。

二,区间询问怎么做?`````假设左端点$x$,那么右端点向右开始挪,当不合法(也就是区间被覆盖了)的时候后面都不合法了。再看以$x-1$为左端点,首先不合法的右端点只会比$x$的小。。所以,我们维护这样一个$rb_i$表示最早找到的一个右端点使得这个区间$[i,rb_i]$覆盖了某给定区间,那么他是单调不减的(就是上面这个说明)。那么,为了计算所有不合法子区间,只要计算$\sum\limits_{i\in [l,r],rb_i\le r}(r-rb_i+1)=(x-l+1)(r+1)-\sum\limits_{i=l}^{x}rb_i$。这里的$x$是最靠右的$i$,且$i\in [l,r],rb_i\le r$。为了找到$x$,利用上述$rb$单调性质,直接二分查找即可。sum的部分可以直接前缀和预处理。然后即可快速计算答案。

有关仙人掌的坑。。有空再补。。虽然这题似乎和仙人掌没啥太大关系

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=3e5+;
struct thxorz{
int to[N<<],nxt[N<<],head[N],tot;
inline void add(int x,int y){
to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
}
}G;
ll sum[N];
int n,m,q,L,R,l,r;
int rb[N];
#define y G.to[j]
int dfn[N],low[N],tim,stk[N],Top,rt;
void tarjan(int x){//dbg(x);
dfn[x]=low[x]=++tim;
if(rt==x&&!G.head[x])return;
stk[++Top]=x;
for(register int j=G.head[x];j;j=G.nxt[j]){
if(!dfn[y]){
tarjan(y),MIN(low[x],low[y]);
if(low[y]>=dfn[x]){
int tmp,mi=n+,ma=,cnt=;
do MIN(mi,tmp=stk[Top--]),MAX(ma,tmp),++cnt;while(tmp^y);
MIN(mi,x),MAX(ma,x),++cnt;//dbg2(mi,ma);
if(cnt>)MIN(rb[mi],ma);
}
}
else MIN(low[x],dfn[y]);
}
}
#undef y
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n),read(m);
for(register int i=,x,y;i<=m;++i)read(x),read(y),G.add(x,y);
fill(rb+,rb+n+,n+);
for(register int i=;i<=n;++i)if(!dfn[i])Top=,tarjan(i);
for(register int i=n-;i;--i)MIN(rb[i],rb[i+]);//dbg2(i,rb[i]);
for(register int i=;i<=n;++i)sum[i]=sum[i-]+rb[i];
read(q);for(register int i=,L,R,mid;i<=q;++i){
l=read(L),r=read(R);--L;
while(L<R){
mid=L+R+>>;
if(rb[mid]<=r)L=mid;
else R=mid-;
}//dbg(L);
printf("%I64d\n",(r-l+)*1ll*(r-l+)/-((L-l+)*1ll*(r+)-(sum[L]-sum[l-])));
}
return ;
}

总结:主要在问题二上卡住了。主要还是考虑从暴力入手,因为这个子区间问题基本思路就是固定左端点,算右端点,因为这题有两个单调的地方,所以可以用前缀和优化。

CF901C Bipartite Segments[点双+二分+前缀优化]的更多相关文章

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

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

  2. 【CF587D】Duff in Mafia 二分+前缀优化建图+2-SAT

    [CF587D]Duff in Mafia 题意:给你一张n个点m条边的无向图,边有颜色和边权.你要从中删去一些边,满足: 1.任意两条删掉的边没有公共的顶点.2.任意两条剩余的.颜色相同的边没有公共 ...

  3. CF901C. Bipartite Segments

    n<=300000,m<=300000的图,图上只有奇环,q<=300000个询问每次问:一个区间内有多少个子区间,满足只保留编号在该区间的点以及他们之间的边,可以构成一个二分图. ...

  4. Codeforces 901C Bipartite Segments

    Bipartite Segments 因为图中只存在奇数长度的环, 所以它是个只有奇数环的仙人掌, 每条边只属于一个环. 那么我们能把所有环给扣出来, 所以我们询问的区间不能包含每个环里的最大值和最小 ...

  5. 【CodeForces】901 C. Bipartite Segments

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

  6. POJ 3061 (二分+前缀和or尺取法)

    题目链接: http://poj.org/problem?id=3061 题目大意:找到最短的序列长度,使得序列元素和大于S. 解题思路: 两种思路. 一种是二分+前缀和.复杂度O(nlogn).有点 ...

  7. Codeforces Round #381 (Div. 2) D. Alyona and a tree 树上二分+前缀和思想

    题目链接: http://codeforces.com/contest/740/problem/D D. Alyona and a tree time limit per test2 secondsm ...

  8. Poj 3061 Subsequence(二分+前缀和)

    Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12333 Accepted: 5178 Descript ...

  9. Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化

    设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子 转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就 ...

随机推荐

  1. HDU4513 【mannacher算法】

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4513 Problem Description 吉哥又想出了一个新的完美队形游戏! 假设有n个人按顺序站在 ...

  2. 学习笔记:CentOS7学习之十八:Linux系统启动原理及故障排除

    目录 学习笔记:CentOS7学习之十八:Linux系统启动原理及故障排除 18.1 centos6系统启动过程及相关配置文件 18.1.1 centos6系统启动过程 18.1.2 centos6启 ...

  3. 使用pycharm开发web——django2.1.5(一)入坑尝试第一步,基本搭建

    首先,接触python的人应该都会用pip 来安装需要的包吧(------>>>>)默认 在运行中使用python -m django --version来检查自己的djang ...

  4. (五)mybatis开发dao层

    目录 SqlSession 是线程不安全的 原始 dao 开发方法 Mapper 代理方法 关于代理对象 SqlSession 是线程不安全的 SqlSession 是 线程不安全 的: 对于它,我们 ...

  5. Prime Number(CodeForces-359C)【快速幂/思维】

    题意:已知X,数组arr[n],求一个分式的分子与分母的最大公因数.分子为ΣX^arr[i],分母为X^Σarr[i],数组为不递减序列. 思路:比赛的时候以为想出了正确思路,WA掉了很多发,看了别人 ...

  6. 什么是Sprint?

    Sprint指Scrum团队完成一定数量工作所需的短暂.固定的周期.Sprint是Scrum和敏捷的核心,找到正确的Sprint周期将帮助您的敏捷团队交付更高质量的产品. “在Scrum框架中,庞大且 ...

  7. Python 正则表达模块详解

    Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...

  8. hdu 3500 还是搜索

    这道题目由于每走一步的时候毛毛球是可以变换的 换言之 主体不唯一 所以这里搜索的设计有变化 再就是几个回溯的过程要注意.,.  小心使得万年船 #include <iostream> #i ...

  9. 7-MySQL DBA笔记-研发规范

    第7章 研发规范 本章将为读者解读一份研发规范.为了更好地协同工作和确保所开发的应用尽可能的稳定.高效,建立一套数据库相关的研发规范是很有必要的,虽然研发规范的确立和推广是一项很耗时的工作,但所取得的 ...

  10. JAVA学习篇--静态代理VS动态代理

    本篇博客的由来,之前我们学习大话设计,就了解了代理模式,但为什么还要说呢? 原因: 1,通过DRP这个项目,了解到了动态代理,认识到我们之前一直使用的都是静态代理,那么动态代理又有什么好处呢?它们二者 ...