首页 > 其他分享 >CF1628E Groceries in Meteor Town 题解

CF1628E Groceries in Meteor Town 题解

时间:2024-02-11 22:44:08浏览次数:36  
标签:Town int 题解 up dfs read ext Groceries define

题目链接

点击打开链接

题目解法

感觉就是很多个套路组合出来,但我有些套路都不会/ll

  • 套路1
    看到从一点出发,到其他点的路径上的最大权,可以想到 \(kruskal\) 生成树(这提示我不仅是图可以用 \(kruskal\) 生成树,树也可以捏)
    我们建大根的 \(kruskal\) 生成树,那么将问题转化成了找一个白点 \(y\),使得 \(lca(x,y)\) 的深度最小
  • 套路2
    对于固定的点 \(x\),在一个点集 \(S\) 中选出 \(y\),使得 \(lca(x,y)\) 的深度最小,那么 \(y\) 一定出自点集 \(S\) 中 \(dfs\) 序最小和最大的 \(2\) 个点之一
    这个结论不难感性理解
    这启发我们只要维护当前白点中最小和最大的 \(dfs\) 序的点即可

时间复杂度 \(O(n\log n)\)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
inline int read(){
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    return FF*RR;
}
const int N=600100;
int n,m,V[N];
int lc[N],rc[N],fa[N],up[N][20],depth[N],dfs_clock,dfn[N];
typedef tuple<int,int,int> tup;
tup E[N];
void dfs(int u){
    dfn[u]=++dfs_clock;
    if(lc[u]){
        depth[lc[u]]=depth[rc[u]]=depth[u]+1;
        dfs(lc[u]),dfs(rc[u]);
    }
}
#define fi first
#define se second
struct SGT{
    pii sto[N<<2],seg[N<<2];
    int tag[N<<2];
    void down(int x,int type){
        tag[x]=type;
        if(type) seg[x]=sto[x];
        else seg[x]={-1,-1};
    }
    void pushdown(int x){ if(tag[x]!=-1) down(x<<1,tag[x]),down(x<<1^1,tag[x]),tag[x]=-1;}
    int Upmx(int x,int y){ if(x==-1) return y;if(y==-1) return x;return dfn[x]>dfn[y]?x:y;}
    int Upmn(int x,int y){ if(x==-1) return y;if(y==-1) return x;return dfn[x]<dfn[y]?x:y;}
    pii pushup(pii o1,pii o2){ return {Upmx(o1.fi,o2.fi),Upmn(o1.se,o2.se)};}
    void build(int l,int r,int x){
        tag[x]=-1,seg[x]={-1,-1};
        if(l==r){ sto[x]={l,l};return;}
        int mid=(l+r)>>1;
        build(l,mid,x<<1),build(mid+1,r,x<<1^1);
        sto[x]=pushup(sto[x<<1],sto[x<<1^1]);
    }
    void modify(int l,int r,int x,int L,int R,int type){
        if(L<=l&&r<=R){ down(x,type);return;}
        pushdown(x);
        int mid=(l+r)>>1;
        if(mid>=L) modify(l,mid,x<<1,L,R,type);
        if(mid<R) modify(mid+1,r,x<<1^1,L,R,type);
        seg[x]=pushup(seg[x<<1],seg[x<<1^1]);
    }
}sgt;
int Lca(int x,int y){
    if(depth[x]>depth[y]) swap(x,y);
    DF(i,19,0) if(depth[up[y][i]]>=depth[x]) y=up[y][i];
    if(x==y) return x;
    DF(i,19,0) if(up[x][i]!=up[y][i]) x=up[x][i],y=up[y][i];
    return up[x][0];
}
int get_father(int x){ return x==fa[x]?x:fa[x]=get_father(fa[x]);}
int main(){
    n=read(),m=read();
    F(i,1,n-1){
        int x=read(),y=read(),z=read();
        E[i]={z,x,y};
    }
    sort(E+1,E+n);
    int ext=n;
    F(i,1,n) fa[i]=i;
    F(i,1,n-1){
        auto [z,x,y]=E[i];
        x=get_father(x),y=get_father(y);
        ext++,V[ext]=z;
        up[x][0]=up[y][0]=ext,fa[x]=fa[y]=fa[ext]=ext;
        lc[ext]=x,rc[ext]=y;
    }
    depth[ext]=1,dfs(ext);
    F(j,1,19) F(i,1,ext) up[i][j]=up[up[i][j-1]][j-1];
    sgt.build(1,n,1);
    while(m--){
        int op=read();
        if(op==1){ int l=read(),r=read();sgt.modify(1,n,1,l,r,1);}
        else if(op==2){ int l=read(),r=read();sgt.modify(1,n,1,l,r,0);}
        else{
            int x=read();
            auto [p1,p2]=sgt.seg[1];
            int ans=-1;
            if(p1!=x&&p1!=-1) chkmax(ans,V[Lca(p1,x)]);
            if(p2!=x&&p2!=-1) chkmax(ans,V[Lca(p2,x)]);
            printf("%d\n",ans);
        }
    }
    return 0;
}

标签:Town,int,题解,up,dfs,read,ext,Groceries,define
From: https://www.cnblogs.com/Farmer-djx/p/18013588

相关文章

  • 图上的游戏 题解
    「2020集训队论文」图上的游戏。算法\(1\):给定点集\(S\),\(|S|=n\),其中有\(m\)个好点。每次可以询问指定点集中是否存在好点,求所有好点。询问次数\(O(\min\{m\logn,n\})\)。对\(S\)分治,若当前不存在好点则退出。每个好点被询问\(\lceil\logn\rceil\)次,分治次......
  • CF1715E Long Way Home题解
    题解注意到\(k\)是一个很小的数,我们考虑分层图是否可做,这时航线有\(n^2\)条,我们可能会建出\((k+1)m+kn^2\)条边,空间会炸掉,然而单单从分层图的角度来优化,是困难的。对于\(m=0\)的情况。考虑\(\text{dp}\),定义\(dp_{i,j}\)表示乘坐不超过\(i\)次航班到达\(j\)的最......
  • CF1928E 题解
    \(\textbf{ProblemStatement}\)给定\(n,x,y,s\),构造长度为\(n\)的序列\(a\),满足:\(a_1=x\)。\(\foralli\in[2,n],a_i=a_{i-1}+y\)或者\(a_i=a_{i-1}\bmody\)。\(\sum\limits_{i=1}^na_i=s\)。给出构造或报告无解。\(\sumn,\sums\le......
  • 题解 AT_mujin_pc_2016_c【オレンジグラフ】
    本文中点的编号从\(0\)开始。显然,题目中要求橙色的边构成极大的二分图。枚举二分图左右部分别有哪些点。特别地,钦定\(0\)号点是左部点。将所有跨左右部的边染为橙色,如果所有点通过橙色的边连通,就得到了一组合法的解;如果不连通,显然可以将更多的边染成橙色,使得所有点连通。//......
  • 题解 ABC336G【16 Integers】
    萌萌BEST定理练习题。赛时几乎做出来了,但写挂了,现在在火车上没事干就给补了。考虑建图,图中共有\(8\)个节点,节点的编号是\((\mathbb{Z}/2\mathbb{Z})^3\)的每个元素。对于每个四元组\((i,j,k,l)\in(\mathbb{Z}/2\mathbb{Z})^4\),在图中连\(X_{i,j,k,l}\)条\((i,j,k)\to(j......
  • 洛谷 P1795 无穷的序列 题解
    题目传送门题目大意:给定整数\(a\),判断\(a\)是否属于数列\(1,2,4,7,11\cdots\)。多测。1.暴力枚举(90pts)不难发现,该数列除第一项外第\(n\)项比第\(n-1\)项多\(n-1\)。故暴力枚举\(n\),计算数列的每一项,判断是否与\(a\)相等,大于\(a\)就break。多测加记忆化,用mx......
  • P5524 [Ynoi2012] NOIP2015 充满了希望 题解
    题目链接:充满了希望一开始以为是传统老题,结果看到有个交换单修操作,ODT这题试了下,应该\(fake\)了,毕竟有单修,很难保证之前的\(log\)级复杂度。有些较为智慧的解法确实不好思考,说个很简单的做法,这里没有问颜色数,而是问的颜色具体情况,那就比之前的很多题简单太多了。颜色的具体......
  • AtCoder-abc340_f题解
    题意简述给定整数\(x,y\),询问是否存在整数\(a,b\),满足:\(-10^{18}\lea,b\le10^{18}\)。由\((0,0),(x,y),(a,b)\)三点构成的三角形面积为\(1\)。如果存在,输出任意一组;否则输出-1。思路先假设\(x,y,a,b\)都是正数。那么图大概是这样:此时红色三角形的面积就......
  • P4183 [USACO18JAN] Cow at Large P 题解
    Description贝茜被农民们逼进了一个偏僻的农场。农场可视为一棵有\(N\)个结点的树,结点分别编号为\(1,2,\ldots,N\)。每个叶子结点都是出入口。开始时,每个出入口都可以放一个农民(也可以不放)。每个时刻,贝茜和农民都可以移动到相邻的一个结点。如果某一时刻农民与贝茜相遇了......
  • [AGC062B] Split and Insert 题解
    题目链接点击打开链接题目解法咋神仙区间\(dp\)题永远想不到区间\(dp\)???首先把操作顺序反转那么现在的问题就是:每次可以选出一个子序列放到序列末尾,使序列升序的最小代价这个问题看着也是毫无头绪我尝试去找些规律,当然也没找到考虑精细刻画操作过程:最终的序列是升序的,最......