BZOJ 2759 一个动态树好题 (LCT)
滚回来学文化课了……
题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=2759
题解
LCT,显然的做法是维护链上所有一次函数的复合。
如何处理根的问题?
考虑所有的连通块都建成有根树,另外记录每个根的父亲。
修改父亲的时候,如果修改的是根,那么要么直接改,要么合并两个连通块,根变为非根;如果修改的不是根,要特判分裂了两个连通块导致根的父亲进了新的连通块的情况,如果如此则需重新合并,根变为非根,其余直接改即可。
时间复杂度\(O(n\log n)\).
代码
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cassert>
using namespace std;void read(int &x)
{int f=1;x=0;char s=getchar();while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f;
}const int N = 3e4;
const int P = 1e4+7;
int inv[P+2];
struct Data
{int a,b;Data() {}Data(int _a,int _b) {a = _a,b = _b;}Data operator *(const Data &arg) const {return Data(a*arg.a%P,(b*arg.a+arg.b)%P);}int calc(int x) {return (a*x+b)%P;}int solve(){if(a==0) {return b==0?-2:-1;}return inv[a]*(P-b)%P;}
};
int fa[N+3];
int uf[N+3];
int n,q;int findfa(int u)
{int i = u;while(u!=uf[u]) {u = uf[u];}while(u!=uf[i]){int j = uf[i]; uf[i] = u; i = j;}return u;
}struct SplayNode
{int son[2],fa; Data val,sum;
} spl[N+3];
bool isroot(int u) {return spl[spl[u].fa].son[0]!=u && spl[spl[u].fa].son[1]!=u;}
void pushup(int u)
{int ls = spl[u].son[0],rs = spl[u].son[1];spl[u].sum = spl[u].val;if(ls) {spl[u].sum = spl[ls].sum*spl[u].sum;}if(rs) {spl[u].sum = spl[u].sum*spl[rs].sum;}
}
void rotate(int u)
{int x = spl[u].fa,y = spl[x].fa,dir = u==spl[x].son[0];if(!isroot(x)) {spl[y].son[x==spl[y].son[1]] = u;}spl[u].fa = y;spl[x].son[dir^1] = spl[u].son[dir];if(spl[u].son[dir]) {spl[spl[u].son[dir]].fa = x;}spl[u].son[dir] = x; spl[x].fa = u;pushup(x);
}
void splaynode(int u)
{int x = u;while(!isroot(x)){x = spl[x].fa;}while(!isroot(u)){int y = spl[u].fa,z = spl[y].fa;if(!isroot(y)) {(u==spl[y].son[1])^(y==spl[z].son[1]) ? rotate(u) : rotate(y);}rotate(u);}pushup(u);
}
void access(int u)
{for(int i=0; u; i=u,u=spl[u].fa){splaynode(u);spl[u].son[1] = i;pushup(u);}
}
int findroot(int u,int flg=0)
{access(u); splaynode(u);while(spl[u].son[0]) u = spl[u].son[0];if(flg) splaynode(u);return u;
}
void link(int u,int v) //fa[u]=v
{
// printf("link %d %d\n",u,v);access(u); splaynode(u);spl[u].fa = v;
}
void cut(int u) //fa[u]=v
{
// printf("cut %d\n",u);access(u); splaynode(u);int v = spl[u].son[0]; spl[u].son[0] = spl[v].fa = 0;pushup(u);
}
void modify(int u,Data x)
{splaynode(u);spl[u].val = x;
}int main()
{inv[1] = 1; for(int i=2; i<P; i++) inv[i] = P-(P/i*inv[P%i]%P);scanf("%d",&n);for(int i=1; i<=n; i++) uf[i] = i;for(int i=1; i<=n; i++){int u,x,y; scanf("%d%d%d",&x,&u,&y);spl[i].val = spl[i].sum = Data(x,y);int uu = findfa(u);if(uu==i){fa[i] = u;}else{link(i,u);uf[findfa(i)] = uu;}}scanf("%d",&q);while(q--){char opt[5]; scanf("%s",opt+1);if(opt[1]=='A'){int u; scanf("%d",&u);int rt = findroot(u);access(fa[rt]); splaynode(fa[rt]);int x = Data((spl[fa[rt]].sum.a-1+P)%P,spl[fa[rt]].sum.b).solve();if(x<0) {printf("%d\n",x);}else{access(u); splaynode(u);int ans = spl[u].sum.calc(x);printf("%d\n",ans);}}else if(opt[1]=='C'){int u,ax,ay,v; scanf("%d%d%d%d",&u,&ax,&v,&ay);modify(u,Data(ax,ay));if(fa[u]){int rtv = findroot(v);if(rtv==u) {fa[u] = v;}else{fa[u] = 0;link(u,v);}}else{int rt = findroot(u);cut(u);int rtf = findroot(fa[rt]);if(rtf==u){link(rt,fa[rt]);fa[rt] = 0;}int rtv = findroot(v);if(rtv==u) {fa[u] = v;}else {link(u,v);}}}}return 0;
}
BZOJ 2759 一个动态树好题 (LCT)相关推荐
- BZOJ2759 一个动态树好题
题目 有\(N\)个未知数\(x[1..n]\)和\(N\)个等式组成的同余方程组: \(x[i]=k[i]*x[p[i]]+b[i] mod 10007\) 其中,\(k[i],b[i],x[i]∈ ...
- 【bzoj2759】一个动态树好题
Portal -->bzoj2759 Solution 哇我感觉这题真的qwq是很好的一题呀qwq 很神qwq反正我真的是自己想怎么想都想不到就是了qwq 首先先考虑一下简化版的问题应该怎么解决 ...
- BZOJ 3730: 震波 动态树分治 线段树 lca
3730: 震波 Time Limit: 15 Sec Memory Limit: 256 MB Submit: 1202 Solved: 288 [Submit][Status][Discuss ...
- luoguP3690 【模板】Link Cut Tree (动态树)[LCT]
题目背景 动态树 题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- SPOJ OTOCI 动态树 LCT
SPOJ OTOCI 裸的动态树问题. 回顾一下我们对树的认识. 最初,它是一个连通的无向的无环的图,然后我们发现由一个根出发进行BFS 会出现层次分明的树状图形. 然后根据树的递归和层次性质,我们得 ...
- 动态树(LCT)初探
文章目录 前置技能 那么直接开始吧 原树与辅助树 Access操作 含义 Addition: Splay 旋转操作 Splay操作 辅助树上的Access MakeRoot操作 Link操作 Cut操 ...
- 树套树 ---- 树状数组套权值线段树模板题 P2617 Dynamic Rankings 动态第K大
题目链接 题目大意: 给你一个数组aaa,aaa有两个操作 询问aaa中[l,r][l,r][l,r]区间里面第kkk小的数是哪个? 修改axa_xax为yyy 解题思路: 首先我们知道权值线段树是 ...
- bzoj 3730: 震波 动态点分治+树链剖分+线段树
##### 题目描述 : 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并且随 ...
- Luogu P1198 BZOJ 1012 最大数 (线段树)
Luogu P1198 BZOJ 1012 最大数 (线段树) 手动博客搬家: 本文发表于20170821 14:32:05, 原地址https://blog.csdn.net/suncongbo/a ...
最新文章
- 217. Contains Duplicate - LeetCode
- 华为第四代服务器芯片Hi1620,华为第四代自研芯片Hi1620曝光, 全球首款7nm的ARM处理器...
- 怎么在uefi解锁磁盘_系统重装时,如何秒判Windows启动是UEFI/Legacy?3步就够了!...
- java怎么输出9 99的形式_java如何输出99乘法表
- leetcode543. 二叉树的直径
- Visual Studio下的 JS CSS 压缩和编辑插件
- MySQL 5.7.25 在Windows 7中安装的记录
- 操作系统原理(五)存储管理
- python读取pdf内容转word_卧槽!Pdf转Word用Python轻松搞定!
- DataRow[] /数组转换datatable!
- Rhino(Grasshopper)+PaddleX快速建模
- vMix(视频混合器软件)v22.0.0.48免费版
- 金士顿DT100G3(16G) U盘修复
- JavaScript零基础入门 11:JavaScript实现图片上传并预览
- 抖音最近很火的游戏直播:挤地铁教程+源码+软件下载
- 打破国外垄断 数字音频国家标准DRA颁布
- 使用火焰图(FlameGraph)分析程序性能
- 技术的真相 | 从AR口红试妆了解人工智能试妆技术
- NEON优化:软件性能优化、降功耗怎么搞?
- 深度学习-Word Embedding的详细理解(包含one-hot编码和cos余弦相似度)