【CodeForces】901 C. Bipartite Segments

【题目】C. Bipartite Segments

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

【算法】Tarjan缩点(找环)

【题解】如果两个奇数长度的环相交,会得到一个偶数长度的简单环。所以原图是不存在偶数长度环的仙人掌(每条边只属于一个简单环)。

二分图的定义:一个图是二分图当且仅当不存在奇数长度的环。在当前仙人掌上,二分图实际上要求选择的点不存在环

也就是对于图上已有的每个环x有最小编号点min(x)和最大编号点max(x),区间不能同时包含min(x)和max(x)。(找环可以用Tarjan缩点)

为了统计区间数量,我们预处理r[i]表示以i为区间左端点,区间右端点最远到达r[i],初始r[min(x)]=max(x)-1,然后统计后缀最小值就可以得到r[]数组。

对于询问的区间i∈[l,r],若i>r则ans+=r-i+1,否则ans+=r[i]-i+1。容易发现r[]数组单调递增,所以可以二分求解转折点。

复杂度O(n log n)。

边编号不能为0 QAQ

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
int read(){
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c==‘-‘)t=-1;
    do{s=s*10+c-‘0‘;}while(isdigit(c=getchar()));
    return s*t;
}
const int maxn=300010;
int tot=1,first[maxn],low[maxn],dfn[maxn],dfsnum=0,c[maxn],n,m,mins[maxn],maxs[maxn],s[maxn],d[maxn];
ll sum[maxn],ss[maxn];
bool iscut[maxn];
struct edge{int v,from;}e[maxn*2];
void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}//
void tarjan(int x,int fa){
    low[x]=dfn[x]=++dfsnum;
    for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
        if(!dfn[e[i].v]){
            tarjan(e[i].v,x);
            low[x]=min(low[x],low[e[i].v]);
            if(low[e[i].v]>dfn[x])iscut[i]=iscut[i^1]=1;
        }else low[x]=min(low[x],dfn[e[i].v]);
    }
}
void dfs(int x,int y){
    c[x]=y;d[y]++;
    for(int i=first[x];i;i=e[i].from)if(!iscut[i]&&!c[e[i].v])dfs(e[i].v,y);
}

int main(){
    n=read();m=read();
    for(int i=1;i<=m;i++){
        int u=read(),v=read();
        insert(u,v);insert(v,u);
    }
    tarjan(1,0);int cnt=0;
    for(int i=1;i<=n;i++)if(!c[i])dfs(i,++cnt);
    memset(mins,0x3f,sizeof(mins));
    for(int i=1;i<=n;i++){
        mins[c[i]]=min(mins[c[i]],i);
        maxs[c[i]]=max(maxs[c[i]],i);
    }
    for(int i=1;i<=n;i++)s[i]=n;
    for(int i=1;i<=cnt;i++)if(d[i]>1)s[mins[i]]=maxs[i]-1;
    for(int i=n-1;i>=1;i--)s[i]=min(s[i],s[i+1]);
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(s[i]-i+1),ss[i]=ss[i-1]+i;
    int q=read();
    while(q--){
        int u=read(),v=read();
        int x=lower_bound(s+u,s+v+1,v)-s;
        ll ans=0;
        ans+=sum[x-1]-sum[u-1];
        ans+=1ll*(v-x+1)*(v+1)-(ss[v]-ss[x-1]);
        printf("%lld\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/onioncyc/p/8133813.html

时间: 2024-07-30 05:36:12

【CodeForces】901 C. Bipartite Segments的相关文章

【Codeforces】Gym 101173B Bipartite Blanket 霍尔定理+状压DP

题意 给一张$n\times m$二分图,带点权,问有多少完美匹配子集满足权值和大于等于$t$ 这里有一个结论:对于二分图$\mathbb{A}$和$\mathbb{B}$集合,如果子集$A \in \mathbb{A},B \in \mathbb{B}$,且$A,B$分别是完美匹配的子集,那么$A \cup B$属于一个完美匹配 有了这个结论之后,考虑单侧,枚举子集$S$,利用霍尔定理判定$S$是否是完美匹配,并通过dp转移状态,记录下单侧所有满足条件的权值和,然后两侧一起考虑累加得到答案 时

【codeforces】【比赛题解】#854 CF Round #433 (Div.2)

cf一如既往挺丧 看丧题点我! [A]分数 Petya是数学迷,特别是有关于分数的数学.最近他学了所谓一个分数被叫做"真分数"当且仅当其分子小于分母,而一个分数被叫做"最简分数"当且仅当其分子分母互质.在闲暇时间,Petya在用计算器研究:如何把最简真分数转换为小数等问题.有一天他不小心把除号(÷)按成了加号(+),导致他得到了分子与分母的和.Petya想要得到他原来的分数,但他很快发现这不是唯一的.所以现在他想要知道最大的最简真分数使得其分子与分母的和为n. 输入

【CodeForces】835D Palindromic characteristics

[算法]区间DP [题解]涉及回文问题的区间DP都可以用类似的写法,就是h[i][j]表示i~j是否回文,然后就可以O(1)判断回文了. f[i][j]=k表示该字符串是k-th字符串,因为首先要求回文,既然回文那么左半边和右半边就肯定一样了. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=5010; int f[maxn][maxn]

【codeforces】【比赛题解】#849 CF Round #431 (Div.2)

cf的比赛越来越有难度了--至少我做起来是这样. 先看看题目吧:点我. 这次比赛是北京时间21:35开始的,算是比较良心. [A]奇数与结束 "奇数从哪里开始,又在哪里结束?梦想从何处起航,它们又是否会破灭呢?" 给定一个长度为n的序列.确定能不能将序列分成奇数个长度为奇数的非空字串,而且这其中每个子串以奇数开头,以奇数结尾.可以只分成一个(1也是奇数). 输入 第一行一个正整数n,表示序列长度. 第二行n个整数,表示序列中的元素. 输出 输出"Yes"或"

【CodeForces】841C. Leha and Function(Codeforces Round #429 (Div. 2))

[题意]定义函数F(n,k)为1~n的集合中选择k个数字,其中最小数字的期望. 给定两个数字集A,B,A中任意数字>=B中任意数字,要求重组A使得对于i=1~n,sigma(F(Ai,Bi))最大. [算法]数学结论+数学期望+排序 [题解]很无奈,这题放在div2 C,难以推导的期望公式,广为人知的结论,容易观察样例得出的做法,都体现了这道题的不合理性. F(n,k)=(n+1)/(k+1) 公式推导可能触及我的知识盲区了QAQ 得到公式后,显然要求k尽可能小,n尽可能大,经验告诉我们随着两数

【CodeForces】585 E. Present for Vitalik the Philatelist

[题目]E. Present for Vitalik the Philatelist [题意]给定n个数字,定义一种合法方案为选择一个数字Aa,选择另外一些数字Abi,满足?gcd(Aa,Abi)=1,且gcd(Ab1...Abx)≠1,求方案数取模1e9+7.2<=n<=5*10^5,2<=ai<=10^7. [算法]数论,计数问题 [题解]

【CodeForces】578 C. Weakness and Poorness

[题目]C. Weakness and Poorness [题意]给定含n个整数的序列ai,定义新序列为ai-x,要使新序列的最大子段和绝对值最小,求实数x.n<=2*10^5. [算法]二分||三分||计算几何(凸包) [题解]Editorial 令正数最大子段和为A,负数最大子段和为B,绝对值是max(A,B).当x从小到大变化时,A由大变小,B由小变大. 容易发现这是一个下凸函数,可以用三分法求解. 但是,这道题卡精度(-11会WA,-12会T),解决方法是根据复杂度把循环次数卡到极限而不

【CodeForces】F. Letters Removing

[题目]F. Letters Removing [题意]给定只含小写字母.大写字母和数字的字符串,每次给定一个范围要求删除[l,r]内的字符c(l和r具体位置随删除变动),求m次操作后的字符串.n<=2*10^5. [算法]树状数组+平衡树(set) [题解]因为坐标是序列变动后的,动态坐标可以转化为找到第l个存在的数字到第r个存在的数字之间的范围. 将序列中存在记为1,删除记为0,转化为找前缀和恰好为l和r的位置,这是树状数组的经典操作,详见这篇题解介绍的方法(简单的排名功能) 找到l和r在原

【CodeForces】D. Roads in Yusland

[题目]D. Roads in Yusland [题意]给定n个点的树,m条严格从下往上的路径,每条路径代价ci,求最少代价使得路径覆盖所有边.n,m<=3*10^5,ci<=10^9. [算法]树形DP+线段树||可并堆 [题解]