zoukankan      html  css  js  c++  java
  • [Luogu4230]连体病原体

    题面戳我

    sol

    很好想+很好写的一道题,然而比赛中我还是没有切掉qaq。
    LCT
    枚举左端点(i),向右移动右端点指针(j)找到第一个成环的位置。此时([i,j],[i,j+1]...[i,m])都是合法答案。可见就是在区间([i,j])上区间加(m-j+1),再在([j+1,m])上加上一个等差数列(m-j,m-j-1...1)
    等差数列直接二阶差分最后做两次前缀和即可。

    以下内容摘自出题人题解

    时间复杂度O(nlogn) ,期望得分100分,实际得分75~100分
    FAQ:为什么我写了LCT却只得了75分/90分
    A:因为findroot后要splay才能保证复杂度,不splay的都被我卡到O(n^2)啦!

    发现自己以前写的LCT从来没有在findroot后splay。细思极恐。

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 1000005;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    int m,u[N],v[N],o[N<<1],fa[N],ch[2][N],rev[N],Stack[N],top,t1[N],t2[N];
    bool son(int x){return x==ch[1][fa[x]];}
    bool isroot(int x){return x!=ch[0][fa[x]]&&x!=ch[1][fa[x]];}
    void reverse(int x){if(!x)return;swap(ch[0][x],ch[1][x]);rev[x]^=1;}
    void pushdown(int x){if(!rev[x])return;reverse(ch[0][x]);reverse(ch[1][x]);rev[x]=0;}
    void rotate(int x)
    {
    	int y=fa[x],z=fa[y],c=son(x);
    	ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
    	fa[x]=z;if (!isroot(y)) ch[son(y)][z]=x;
    	ch[c^1][x]=y;fa[y]=x;
    }
    void splay(int x)
    {
    	Stack[top=1]=x;
    	for (int y=x;!isroot(y);y=fa[y]) Stack[++top]=fa[y];
    	while (top) pushdown(Stack[top--]);
    	for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
    		if (!isroot(y)) son(x)^son(y)?rotate(x):rotate(y);
    }
    void access(int x){for (int y=0;x;y=x,x=fa[x]) splay(x),ch[1][x]=y;}
    void makeroot(int x){access(x);splay(x);reverse(x);}
    int findroot(int x){access(x);splay(x);while(ch[0][x])x=ch[0][x];splay(x);return x;}
    void split(int x,int y){makeroot(x);access(y);splay(y);}
    void link(int x,int y){makeroot(x);fa[x]=y;}
    void cut(int x,int y){split(x,y);ch[0][y]=fa[x]=0;}
    int main()
    {
    	m=gi();
    	for (int i=1;i<=m;++i) u[i]=gi(),v[i]=gi();
    	for (int i=1,j=1;i<=m;cut(u[i],v[i]),++i)
    	{
    		while (j<=m&&findroot(u[j])!=findroot(v[j])) link(u[j],v[j]),++j;
    		if (j<=m) t1[i]+=m-j+1,t2[j+1]--;
    	}
    	for (int i=1;i<=m;++i) t2[i]+=t2[i-1];
    	for (int i=1;i<=m;++i) t1[i]+=t1[i-1],t2[i]+=t2[i-1];
    	for (int i=1;i<=m;++i) printf("%d ",t1[i]+t2[i]);
    	return 0;
    }
    
  • 相关阅读:
    为MySQL的root用户设定密码
    Sublime Text 3安装Package Control失败
    从系统关机后主机仍在运行
    如何判断一个数是否是质数?
    python之lambda函数
    yum的一些命令使用方法
    NopCommerce架构分析-数据持久层
    NopCommerce架构分析-Cache的应用
    NopCommerce架构分析-源码结构和架构
    下载图片
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8457367.html
Copyright © 2011-2022 走看看