首页 > 其他分享 >[BZOJ3159] 决战 题解

[BZOJ3159] 决战 题解

时间:2025-01-09 17:23:01浏览次数:1  
标签:BZOJ3159 决战 int 题解 void pos fa sn push

个人感觉各方面难度高于《在美妙的数学王国中畅游》,也不知道是不是求导的关系,这题 \(luogu\) 难度评级还更低。不过感觉这题作完对 \(LCT\) 理解更顺畅了。


前四个操作简单,关键在第五人格操作。

注意力惊人的注意到我们无法像普通 \(Splay\) 一样,直接对 \(LCT\) 中的 \(Splay\) 进行区间反转。因为 \(LCT\) 中的 \(Splay\) 同时维护树的形态 \(id\) 和权值 \(val\)。

那我们干脆把这俩玩意分别处理,相当于建 \(id\ tree\) 和 \(val\ tree\)。由于 \(Splay\) 的操作都是在根处进行,所以我们只需要对于每个根节点 \(rt\) 记录 \(pos_{rt}\) 表示对应另一棵树中自己的编号,就可以完成查询。小改 \(rotate,link\),魔改 \(access\),再加一个 \(setpos\) 用来找 \(pos_{rt}\) 即可。

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

#include<bits/stdc++.h>
#define ll long long
#define fa(x) lct[x].fa
#define fl(x) lct[x].fl
#define mx(x) lct[x].mx
#define mn(x) lct[x].mn
#define sz(x) lct[x].sz
#define ad(x) lct[x].ad
#define val(x) lct[x].val
#define sum(x) lct[x].sum
#define sn(x,i) lct[x].sn[i]
using namespace std;
const int N=1e5+5;
struct node{
    int sn[2],val;ll sum;
    int mx,mn,fa,fl,sz,ad;
}lct[N];int n,m,tp,st[N];
int pos[N],flg;string s;
int check(int x){
    return sn(fa(x),0)!=x&&sn(fa(x),1)!=x;
}int chksn(int x){
    return sn(fa(x),1)==x;
}void push_up(int x){
    sz(x)=sz(sn(x,0))+sz(sn(x,1))+1;
    sum(x)=sum(sn(x,0))+sum(sn(x,1))+val(x);
    mx(x)=max({mx(sn(x,0)),mx(sn(x,1)),val(x)});
    mn(x)=min({mn(sn(x,0)),mn(sn(x,1)),val(x)});
}void push(int x){
    if(!x) return;fl(x)^=1;
    swap(sn(x,0),sn(x,1));
}void down(int x,int a){
    if(!x) return;
    sum(x)+=(ll)sz(x)*a,val(x)+=a;
    ad(x)+=a,mx(x)+=a,mn(x)+=a;
}void push_down(int x){
    if(!x) return;
    if(fl(x)){
        push(sn(x,0));
        push(sn(x,1));
    }down(sn(x,0),ad(x));
    down(sn(x,1),ad(x));
    fl(x)=ad(x)=0;
}void rotate(int x){
    int y=fa(x),z=fa(y),k=chksn(x);
    if(check(y)) pos[x]=pos[y];
    else sn(z,chksn(y))=x;
    fa(x)=z,fa(y)=x,fa(sn(x,1-k))=y;
    sn(y,k)=sn(x,1-k),sn(x,1-k)=y;
    push_up(y);
}void splay(int x){
    st[tp=1]=x;
    for(int i=x;!check(i);i=fa(i)) st[++tp]=fa(i);
    while(tp) push_down(st[tp--]);
    while(!check(x)){
        int y=fa(x),z=fa(y);
        if(!check(y))
            rotate(chksn(x)!=chksn(y)?x:y);
        rotate(x);
    }push_up(x);
}int find(int x,int k){
    push_down(x);
    if(sz(sn(x,0))+1==k) return x;
    if(sz(sn(x,0))>=k) return find(sn(x,0),k);
    return find(sn(x,1),k-sz(sn(x,0))-1);
}void setpos(int x){
    splay(x),splay(pos[x]);
    pos[x]=find(pos[x],sz(sn(x,0))+1);
    splay(pos[x]);
}void access(int x){
    setpos(x);int y=sn(x,1),z=sn(pos[x],1);
    pos[y]=z,fa(z)=0,sn(x,1)=sn(pos[x],1)=0;
    push_up(x),push_up(pos[x]);
    while(fa(x)){
        setpos(x),setpos(fa(x));
        pos[sn(fa(x),1)]=sn(pos[fa(x)],1);
        sn(fa(x),1)=x,fa(sn(pos[fa(x)],1))=0;
        sn(pos[fa(x)],1)=pos[x];
        fa(pos[x])=pos[fa(x)];
        push_up(pos[fa(x)]);
        push_up(fa(x)),x=fa(x);
    }
}void mk(int x){
    access(x),setpos(x);
    push(x),push(pos[x]);
}void split(int x,int y){
    mk(x),access(y),setpos(y);
}void link(int x,int y){
    mk(x),setpos(y),fa(x)=y;
}signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    mn(0)=1e18,cin>>n>>m>>tp;
    for(int i=1;i<=n;i++)
        sz(i)=sz(i+n)=1,pos[i]=i+n,pos[i+n]=i;
    for(int i=1,x,y;i<n;i++)
        cin>>x>>y,link(x,y);
    while(m--){
        int x,y,w;cin>>s>>x>>y;split(x,y);
        if(s=="Increase") cin>>w,down(pos[y],w);
        if(s=="Sum") cout<<sum(pos[y])<<"\n";
        if(s=="Major") cout<<mx(pos[y])<<"\n";
        if(s=="Minor") cout<<mn(pos[y])<<"\n";
        if(s=="Invert") push(pos[y]);
    }return 0;
}

标签:BZOJ3159,决战,int,题解,void,pos,fa,sn,push
From: https://www.cnblogs.com/chang-an-22-lyh/p/18662539/bzoj3159-jue_zhan-tj

相关文章

  • Kubernetes集群运维生产常见问题解析与解决方案
    前言:在Kubernetes集群的日常运维工作中,我们难免会遇到各种各样的问题。这些问题可能涉及到集群的部署、配置、监控、性能优化等多个方面。为了解决这些问题,我们需要不断地学习和积累经验。在这里,我打算收集并整理一些网友曾经提出的问题,并提供相应的解析和解决方案,之前的问题无从......
  • 2024 年 06 月 GESP C++ 一级真题解析
    ......
  • [THUWC2017] 在美妙的数学王国中畅游 题解(内附求导小技巧)
    事实证明物竞笔记是个好东西,可惜没带,不然还能谎称自己会一点求导和微积分。顺便在这里把比较经典的一些关于求导的东西记录一下:常用函数求导:\(C'=0,(x^n)'=nx^{n-1},(\log_ax)'=\frac1{x\lna}\)\((\lnx)'=\frac1x,(a^x)'=a^x\lna,(e^x)'=e^x\)\((\sinx)'=\cosx=\sin(......
  • [THUWC2017] 在美妙的数学王国中畅游 题解(内附求导小技巧)
    事实证明物竞笔记是个好东西,可惜没带,不然还能谎称自己会一点求导和微积分。顺便在这里把比较经典的一些关于求导的东西记录一下:常用函数求导:\(C'=0,(x^n)'=nx^{n-1},(\log_ax)'=\frac1{x\lna}\)\((\lnx)'=\frac1x,(a^x)'=a^x\lna,(e^x)'=e^x\)\((\sinx)'=\cosx=\sin(......
  • Luogu P2292 HNOI2004 L 语言 题解 [ 紫 ] [ AC 自动机 ] [ 状压 dp ]
    L语言:很好的一道状压dp题。思路看到这题,首先可以想到一个很暴力的dp,设\(dp_i\)表示考虑到第\(i\)位能否被理解,暴力匹配字符串转移即可。第一个优化也很显然,暴力匹配字符串换成AC自动机即可。但是时间复杂度变成了\(O(m|T||S|)\)的,显然会被卡。状压与位运算优化......
  • 洛谷 P2754 [CTSC1999] 家园 / 星际转移问题——题解
    #ifdefONLINE_JUDGE#else#defineQiu_Cheng#endif#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;//typedeflonglongll;constintN=2e6+5,mod=1e9+7,inf=INT_MAX;//constintmod1=469762049,mod2=998244353,mod3=1004535......
  • P7603 [THUPC2021] 鬼街 题解
    P7603[THUPC2021]鬼街题解第一次见折半报警器的trick,记录一下首先观察到\(x\len\le10^5\),所以\(x\)最多有6个质因数,\(x=30030\)可以取到,这使得对于修改,我们可以暴力单点修改。接下来考虑询问,朴素的做法是:每一次灵异事件之后,都对所有监控器进行检验是否满足和......
  • 洛谷 P1550 [USACO08OCT] Watering Hole G 题解
     由于无法提交题解所以来csdn蹭个位置  题目链接  这道题我的思路就是用并查集(推荐先学习:并查集(B站视频))将所有农场连接成n个(几个都不重要)连通块,用一个优先队列(由于作者没找视频所以不放链接了sorry)记录x农场连接y农场的最小价格。  有个值......
  • vue3项目yarn install遇到的info There appears to be trouble with your network con
    新接手的vue3项目在安装依赖的时候经常下载失败,报错Couldn'tfindpackage...onthe"npm"registry或者errorError:readECONNRESET1.可以改变当前的源查看当前使用的源yarnconfiggetregistry改变源yarnconfigsetregistryhttps://registry.npmmirror.com(推荐......
  • [WC2006] 水管局长 题解
    最大值最小的路径肯定在最小生成树上,考虑用\(LCT\)维护最小生成树,只需要维护长度最长的边即可实现。由于\(LCT\)维护最小生成树不支持删边,所以采用倒序加边的方式处理。时间复杂度\(O(n\logn)\)。#include<bits/stdc++.h>#definefa(x)lct[x].fa#definefl(x)lct[x].f......