zoukankan      html  css  js  c++  java
  • [BZOJ2959] 长跑

    Description

      某校开展了同学们喜闻乐见的阳光长跑活动。为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动。一时间操场上熙熙攘攘,摩肩接踵,盛况空前。
      为了让同学们更好地监督自己,学校推行了刷卡机制。
      学校中有n个地点,用1到n的整数表示,每个地点设有若干个刷卡机。
      有以下三类事件:
      1、修建了一条连接A地点和B地点的跑道。
      2、A点的刷卡机台数变为了B。
      3、进行了一次长跑。问一个同学从A出发,最后到达B最多可以刷卡多少次。具体的要求如下:
      当同学到达一个地点时,他可以在这里的每一台刷卡机上都刷卡。但每台刷卡机只能刷卡一次,即使多次到达同一地点也不能多次刷卡。
      为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从A地点到B地点能刷卡的最多次数。

    Input

      输入的第一行包含两个正整数n,m,表示地点的个数和操作的个数。
      第二行包含n个非负整数,其中第i个数为第个地点最开始刷卡机的台数。
      接下来有m行,每行包含三个非负整数P,A,B,P为事件类型,A,B为事件的两个参数。
      最初所有地点之间都没有跑道。
      每行相邻的两个数之间均用一个空格隔开。表示地点编号的数均在1到n之间,每个地点的刷卡机台数始终不超过10000,P=1,2,3。

    Output

      输出的行数等于第3类事件的个数,每行表示一个第3类事件。如果该情况下存在一种设定跑道方向的方案和路径的方案,可以到达,则输出最多可以刷卡的次数。如果A不能到达B,则输出-1。

    Solution

    注意到在一个双联通分量中每个点都可以被走到,可以把原图缩点,然后求树上距离就好了。

    那么可以用(LCT+)并查集维护边双联通分量。

    可能是我写丑了...我(find\_root)函数跑的特别慢...优化的话比较简单,对(splay)上每个点记一个(mn[x])表示(splay)上的(x)子树最靠左边那个点是什么,我就因为改了这个快了将近(10)倍....

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 4e5+10;
    
    int n,m,v[maxn],top;
    int fa[maxn],son[maxn][2],f[maxn],sum[maxn],val[maxn],rev[maxn],sta[maxn],mn[maxn];
    
    #define ls son[x][0]
    #define rs son[x][1]
    
    int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
    
    int which(int x) {return son[fa[x]][1]==x;}
    int nrt(int x) {return son[fa[x]][0]==x||son[fa[x]][1]==x;}
    
    void update(int x) {
    	sum[x]=sum[ls]+sum[rs]+val[x];
    	mn[x]=ls?mn[ls]:x;
    }
    
    void push_rev(int x) {swap(ls,rs),rev[x]^=1;}
    void pushdown(int x) {if(rev[x]) push_rev(ls),push_rev(rs),rev[x]=0;}
    
    void rotate(int x) {
    	int y=fa[x],z=fa[y],w=which(x);
    	if(nrt(y)) son[z][son[z][1]==y]=x;
    	fa[x]=z,fa[y]=x,fa[son[x][w^1]]=y,son[y][w]=son[x][w^1],son[x][w^1]=y;
    	update(y),update(x);
    }
    
    void splay(int x) {
    	int t=x;while(nrt(t)) sta[++top]=t,t=fa[t];sta[++top]=t;
    	while(top) pushdown(sta[top--]);
    	for(;nrt(x);rotate(x)) if(nrt(fa[x])) rotate(which(fa[x])==which(x)?fa[x]:x);
    	update(x);
    }
    
    void access(int x) {for(int t=0;x;splay(x),rs=t,update(t=x),x=fa[x]=find(fa[x]));}
    
    void make_root(int x) {access(x),splay(x),push_rev(x);}
    
    int find_root(int x) {access(x),splay(x);return mn[x];}
    
    void del(int x,int y) {
    	if(x) val[y]+=val[x],f[x]=y,del(ls,y),del(rs,y);
    }
    
    void link(int x,int y) {
    	x=find(x),y=find(y);
    	if(x==y) return ;
    	make_root(x);
    	if(find_root(y)!=x) fa[x]=y;
    	else splay(x),del(rs,x),rs=0,update(x);
    }
    
    void modify(int x,int r) {
    	int u=find(x);splay(u);
    	val[u]+=r-v[x];v[x]=r;update(u);
    }
    
    int query(int x,int y) {
    	x=find(x),y=find(y);
    	make_root(x);
    	if(x==y) return val[x];
    	if(find_root(y)!=x) return -1;
    	access(y),splay(y);return sum[y];
    }
    
    int main() {
    	read(n),read(m);
    	for(int i=1;i<=n;i++) f[i]=i;
    	for(int i=1;i<=n;i++) read(v[i]),val[i]=v[i];
    	for(int i=1,op,x,y;i<=m;i++) {
    		read(op),read(x),read(y);
    		if(op==1) link(x,y);
    		else if(op==2) modify(x,y);
    		else write(query(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    智能移动机器人背后蕴含的技术——激光雷达
    Kalman Filters
    Fiddler抓HttpClient的包
    VSCode开发WebApi EFCore的坑
    WPF之小米Logo超圆角的实现
    windows react打包发布
    jenkins in docker踩坑汇总
    Using ML.NET in Jupyter notebooks 在jupyter notebook中使用ML.NET ——No design time or full build available
    【Linux知识点】CentOS7 更换阿里云源
    【Golang 报错】exec gcc executable file not found in %PATH%
  • 原文地址:https://www.cnblogs.com/hbyer/p/10483960.html
Copyright © 2011-2022 走看看