• 【刷题】洛谷 P4319 变化的道路


    题目描述

    小 w 和小 c 在 H 国,近年来,随着 H 国的发展,H 国的道路也在不断变化着

    根据 H 国的道路法,H 国道路都有一个值 (w) ,表示如果小 w 和小 c 通过这条道路,那么他们的 L 值会减少 (w) ,但是如果小 w 和 小 c 在之前已经经过了这条路,那么他们的 L 值不会减少

    H 国有 (N) 个国家,最开始 H 国有 (N-1) 条道路,这 (N-1) 条道路刚好构成一棵树

    小 w 将和小 c 从 H 国的城市 1 出发,游览 H 国的所有城市,总共游览 32766 天,对于每一天,他们都希望游览结束后 L 值还是一个正数, 那么他们出发时 L 值至少为多少

    H 国的所有边都是无向边,没有一条道路连接相同的一个城市

    输入输出格式

    输入格式:

    输入第 1 行,一个整数 (N)

    输入第 2 至第 (N) 行,每行三个正整数 (u, v, w) ,表示城市 (u) 与城市 (v) 有一条值为 (w) 道路

    输入第 (N+1) 行,一个整数 (M) ,表示 H 国有 (M) 条正在变化的道路

    输入第 (N+2) 行到第 (N+M+1) 行,每行 5 个整数 (u, v, w, l, r) ,表示城市 (u) 到城市 (v) 有一条值为 (w) 的道路, 这条道路存在于第 (l) 天到第 (r)

    输出格式:

    输出共 32766 行,第 (i) 行表示第 (i) 天游览的 L 值至少为多少

    输入输出样例

    输入样例#1:

    4

    1 3 3

    3 4 4

    2 4 5

    3

    1 2 1 1 2

    2 3 8 2 3

    3 4 2 1 1

    输出样例#1:

    7

    9

    13

    由于版面原因,仅显示三行,接下来32763行都是13

    说明

    第一天,选择 1 -(1)> 2 -(0)> 1 -(3)> 3 -(2)> 4,L 值总共减少了 6,所以 L 值至少为 7

    第二天,选择 1 -(1)> 2 -(0)> 1 -(3)> 3 -(4)> 4,L 值总共减少了 8,所以 L 值至少为 9

    第三天及之后,选择 1 -(3)> 3 -(4)> 4 -(5)> 2,L 值总共减少了 12,所以 L 值至少为 13

    subtask1 : 15分,(N = 100, rm = 233)

    subtask2 : 15分,(N = 1000, rm = 2333)

    subtask3 : 20分,(N = 49998, rm = 32766, l = r)

    subtask4:20分,(N = 49999, rm = 32766, r = rm)

    subtask5:30分,(N = 50000, rm = 32766)

    对于subtask3 : (M = rm) ,对于其他subtask:(M=3 imes rm)

    对于所有数据 : (1leq Nleq 50000, 1leq lleq rleq rmleq 32766, 1leq wleq 10^9)

    题解

    又是一道LCT与其它数据结构结合的题目

    肯定离线做,怎么离线?时间线段树分治

    考虑线段树,一条边在 (l)(r) 中出现,就在线段树中 (l)(r) 的区间加上这条边

    最后访问线段树的每个叶子节点,然后往下递归的时候如果区间上有边的标记,就加边;到叶子节点的时候,算答案;回溯的时候,把在这个区间内加的边又删去。(当然,这个线段树虽然要打标记,但是不会有pushdown的)

    然后就做完了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=200000+10,inf=0x3f3f3f3f;
    int n,m,scnt;
    ll ans;
    struct edge{
    	int u,v,w;
    };
    edge side[MAXN];
    #define lc(x) ch[(x)][0]
    #define rc(x) ch[(x)][1]
    struct LCT{
    	int ch[MAXN][2],fa[MAXN],rev[MAXN],stack[MAXN],cnt,Mx[MAXN],id[MAXN],val[MAXN];
    	inline void init()
    	{
    		memset(Mx,-inf,sizeof(Mx));
    		memset(val,-inf,sizeof(val));
    	}
    	inline bool nroot(int x)
    	{
    		return lc(fa[x])==x||rc(fa[x])==x;
    	}
    	inline void reverse(int x)
    	{
    		std::swap(lc(x),rc(x));
    		rev[x]^=1;
    	}
    	inline void pushup(int x)
    	{
    		Mx[x]=val[x],id[x]=x;
    		if(Mx[lc(x)]>Mx[x])Mx[x]=Mx[lc(x)],id[x]=id[lc(x)];
    		if(Mx[rc(x)]>Mx[x])Mx[x]=Mx[rc(x)],id[x]=id[rc(x)];
    	}
    	inline void pushdown(int x)
    	{
    		if(rev[x])
    		{
    			if(lc(x))reverse(lc(x));
    			if(rc(x))reverse(rc(x));
    			rev[x]=0;
    		}
    	}
    	inline void rotate(int x)
    	{
    		int f=fa[x],p=fa[f],c=(rc(f)==x);
    		if(nroot(f))ch[p][rc(p)==f]=x;
    		fa[ch[f][c]=ch[x][c^1]]=f;
    		fa[ch[x][c^1]=f]=x;
    		fa[x]=p;
    		pushup(f);
    		pushup(x);
    	}
    	inline void splay(int x)
    	{
    		cnt=0;
    		stack[++cnt]=x;
    		for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
    		while(cnt)pushdown(stack[cnt--]);
    		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
    			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
    		pushup(x);
    	}
    	inline void access(int x)
    	{
    		for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
    	}
    	inline void makeroot(int x)
    	{
    		access(x);splay(x);reverse(x);
    	}
    	inline void split(int x,int y)
    	{
    		makeroot(x);access(y);splay(y);
    	}
    	inline void link(int x,int y)
    	{
    		makeroot(x);fa[x]=y;
    	}
    	inline void cut(int x,int y)
    	{
    		split(x,y);fa[x]=lc(y)=0;pushup(y);
    	}
    };
    LCT T1;
    #undef lc
    #undef rc
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char c='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(c!='')putchar(c);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    #define Mid ((l+r)>>1)
    #define lson rt<<1,l,Mid
    #define rson rt<<1|1,Mid+1,r
    struct SEG{
    	std::vector<int> V[MAXN];
    	inline void Update(int rt,int l,int r,int L,int R,int k)
    	{
    		if(L<=l&&r<=R)V[rt].push_back(k);
    		else
    		{
    			if(L<=Mid)Update(lson,L,R,k);
    			if(R>Mid)Update(rson,L,R,k);
    		}
    	}
    	inline void Query(int rt,int l,int r)
    	{
    		std::stack< std::pair<int,int> > S;
    		for(register int i=0,limit=V[rt].size();i<limit;++i)
    		{
    			int u=side[V[rt][i]].u,v=side[V[rt][i]].v,w=side[V[rt][i]].w,sn=V[rt][i]+n;
    			T1.split(u,v);
    			if(w<T1.Mx[v])
    			{
    				ans-=T1.Mx[v]-w;
    				int so=T1.id[v];
    				T1.cut(so,side[so-n].u);T1.cut(so,side[so-n].v);
    				S.push(std::make_pair(so,1));
    				T1.val[sn]=w;
    				T1.link(sn,u);T1.link(sn,v);
    				S.push(std::make_pair(sn,0));
    			}
    		}
    		if(l==r)write(ans+1,'
    ');
    		else Query(lson),Query(rson);
    		while(!S.empty())
    		{
    			std::pair<int,int> now=S.top();
    			S.pop();
    			int sn=now.first;
    			if(!now.second)T1.cut(side[sn-n].u,sn),T1.cut(side[sn-n].v,sn),ans-=side[sn-n].w;
    			else T1.link(side[sn-n].u,sn),T1.link(side[sn-n].v,sn),ans+=side[sn-n].w;
    		}
    	}
    };
    SEG T2;
    #undef Mid
    #undef lson
    #undef rson
    int main()
    {
    	read(n);
    	for(register int i=1;i<n;++i)
    	{
    		int u,v,w,sn=i+n;
    		read(u);read(v);read(w);
    		side[++scnt]=(edge){u,v,w};
    		ans+=w;
    		T1.val[sn]=w;
    		T1.link(sn,u);T1.link(sn,v);
    	}
    	read(m);
    	for(register int i=1;i<=m;++i)
    	{
    		int u,v,w,l,r;
    		read(u);read(v);read(w);read(l);read(r);
    		side[++scnt]=(edge){u,v,w};
    		T2.Update(1,1,32766,l,r,scnt);
    	}
    	T2.Query(1,1,32766);
    	return 0;
    }
    
  • 相关阅读:
    IIS和ASP.NET2.0
    VS.NET里关于不能够使用向导的问题
    CodeFile
    判断一个字符串是否全是数字的多种方法及其性能比较(C#实现)
    托管和非托管资源
    ASP.NET 2.0页面框架的几处变化
    导出QQWry.Dat中IP地址到文件[C#]
    面向对象在数据库应用程序中的应用(dotNet)
    如何取得IP/用户名等信息
    验证Email是否真正存在(上)
  • 原文地址:https://www.cnblogs.com/hongyj/p/8783279.html
Copyright © 2020-2023  润新知