[国家集训队]Tree II

题目

这不是线段树模板2放\(lct\)上了吗

于是开始码码码

之后一直wawawa

于是开始调调调

之后旁边的慎老师看了一看代码就说,你下放乘法标记的时候不乘加法标记吗

我:。。。

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 300005
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    char c=getchar();int x=0;while(c<‘0‘||c>‘9‘) c=getchar();
    while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int n,m;
int fa[maxn],v[maxn],s[maxn],ch[maxn][2],st[maxn],rev[maxn];
inline int nroot(int x) {return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
inline void pushup(int x) {s[x]=s[ch[x][0]]^s[ch[x][1]]^v[x];}
inline void pushdown(int x) {
    if(!rev[x]) return;
    rev[x]=0,rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
    std::swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
    std::swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
}
inline void rotate(int x) {
    int y=fa[x],z=fa[y],k=ch[y][1]==x,w=ch[x][k^1];
    if(nroot(y)) ch[z][ch[z][1]==y]=x;
    ch[x][k^1]=y,ch[y][k]=w;
    pushup(y),pushup(x);fa[w]=y;fa[y]=x,fa[x]=z;
}
inline void splay(int x) {
    int y=x,top=0;
    st[++top]=x;
    while(nroot(y)) st[++top]=fa[y],y=fa[y];
    while(top) pushdown(st[top--]);
    while(nroot(x)) {
        int y=fa[x];
        if(nroot(y)) rotate((ch[y][1]==x)^(ch[fa[y]][1]==y)?x:y);
        rotate(x);
    }
}
inline void access(int x) {
    for(re int y=0;x;y=x,x=fa[x])
        splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x) {
    access(x);splay(x);rev[x]^=1;std::swap(ch[x][0],ch[x][1]);
}
inline int findroot(int x) {
    access(x);splay(x);
    while(ch[x][0]) pushdown(x),x=ch[x][0];
    splay(x);return x;
}
inline void split(int x,int y) {
    makeroot(x);access(y);splay(y);
}
inline void link(int x,int y) {
    makeroot(x);
    if(findroot(y)!=x)fa[x]=y;
}
inline void cut(int x,int y) {
    makeroot(x);
    if(findroot(y)==x&&fa[y]==x&&!ch[y][0]) ch[x][0]=fa[y]=0,pushup(x);
}
int main() {
    n=read(),m=read();
    for(re int i=1;i<=n;i++) v[i]=read();
    int opt,x,y;
    while(m--) {
        opt=read(),x=read(),y=read();
        if(opt==0) split(x,y),printf("%d\n",s[y]);
        if(opt==1) link(x,y);
        if(opt==2) cut(x,y);
        if(opt==3) splay(x),v[x]=y,pushup(x);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/asuldb/p/10367091.html

时间: 2024-10-08 21:56:11

[国家集训队]Tree II的相关文章

P1501 [国家集训队]Tree II

做法 P1501 [国家集训队]Tree II 树上懒惰标记维护动态路径模板题 做法 其实做这题也能练一下对\(LCT\)的了解 我们对\(x,y\)这条路径修改时:\(Split(x,y);....(y)\),传到\(y\)上去就行了 我们发现不管什么操作都会用到\(Access\),其中把底下的点上旋\(splay\)的同时会把\(y\)上的标记取下来 和线段树差不多吧不知道为什么是道黑题 My complete code 写代码(15min)+调试(15min)感觉比模板还容易打 #inc

洛谷P1501 [国家集训队]Tree II

关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2......(相信各位Dalao一定做过这道题) 这里的维护懒标记方法很像.除了翻转标记以外还要维护乘法标记和加法标记. 根据运算优先级,乘法是要先算的,所以先放,放的时候子树的\(sum\),乘法标记,加法标记,儿子的\(val\)统统都要乘一遍. 放加法标记的时候,想到线段树的区间大小是稳定的,而Splay并不是,所以还要

【刷题】洛谷 P1501 [国家集训队]Tree II

题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树: * u v c:将u到v的路径上的点的权值都乘上自然数c: / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数. 输入输出格式 输入格式: 第一行两个整数n,q 接下来n-1行每行两个正整数u,v,

洛谷P1501 [国家集训队]Tree II【LCT】

题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: u v c:将u到v的路径上的点的权值都加上自然数c: u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树: u v c:将u到v的路径上的点的权值都乘上自然数c: / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数. 输入格式: 第一行两个整数n,q 接下来n-1行每行两个正整数u,v,描述这棵树 接下来q行,每

洛谷 P1501 [国家集训队]Tree II

看来这个LCT板子并没有什么问题 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long LL; 5 const LL md=51061; 6 namespace LCT 7 { 8 struct Node 9 { 10 Node *ch[2],*fa; 11 bool rev; 12 LL addv,mulv; 13 LL dat,sum,sz; 14 void pad

题解 luogu P1501【[国家集训队]Tree II】(Link-Cut-Tree)

Link-Cut-Tree 的懒标记下传正确食用方法. 我们来逐步分析每一个操作. 1:+ u v c:将u到v的路径上的点的权值都加上自然数c; 解决方法: 很显然,我们可以 split(u,v) 来提取u,v这一段区间,提取完了将 Splay(v),然后直接在v上打加法标记add即可. 代码: inline void pushadd(ll x,ll val){//打标记 s[x]+=sz[x]*val,v[x]+=val,add[x]+=val; s[x]%=MOD,v[x]%=MOD,ad

[国家集训队2012]tree(陈立杰)

[国家集训队2012]tree(陈立杰) 题目 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树.题目保证有解. INPUT 第一行V,E,need分别表示点数,边数和需要的白色边数.接下来E行每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色). OUTPUT 一行表示所求生成树的边权和. SAMPLE INPUT 2 2 1 0 1 1 1 0 1 2 0 OUTPUT 2 数据规模 0:V<=101,2,3:V<=

【资料】国家集训队论文集(1999~2014)

本文版权归ACShiryu和acvay所有,如转载请注明原作者. 国家集训队1999论文集 1.陈宏:<数据结构的选择与算法效率--从IOI98试题PICTURE谈起> 2.来煜坤:<把握本质,灵活运用--动态规划的深入探讨> 3.齐鑫:<搜索方法中的剪枝优化> 4.邵铮:<数学模型的建立.比较和应用> 5.石润婷:<隐蔽化.多维化.开放化--论当今信息学竞赛中数学建模的灵活性> 6.杨帆:<准确性.全面性.美观性--测试数据设计中的三要素

P1975 [国家集训队]排队

题目 P1975 [国家集训队]排队 做法 逆序对的题当然想办法用cdq做 交换数列的位置好像不好处理,加个时间轴,把交换操作换成:删.删.加.加(位置可变换) 删的贡献系数为\((-1)\),加的贡献系数为\((1)\),然后丢到树状数组也是根据这个系数,这样可以保证不重复统计同一位置 位置为第一维,时间为第二维,注意排序位置时:\(x_1==x_2\)&&\(y_1<y_2\),因为\(y_1\)放到后面会影响\(x_2\)的 My complete code #include&