P5168 xtq玩魔塔
其实就是板子……只要会克鲁斯卡尔重构树和带修莫队就可以了
这么想着的我就调了将近一个下午……
思路其实比较清晰,然而码量很大,细节贼多……
不难看出只在最小生成树上走最优,于是建出克鲁斯卡尔重构树,\(2\)操作直接倍增跳,\(1\)操作和\(3\)操作离线,把克鲁斯卡尔重构树用\(dfs\)序转化为序列之后用带修莫队做
然后……注意细节……这是我的肺腑之言……
//minamoto
#include<bits/stdc++.h>
#define R register
#define inf 0x3f3f3f3f
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=5e5+5,M=3e5+5;
struct eg{int u,v,w;}E[M];
struct ee{int v,nx;}e[N<<1];
int head[N],tot;
inline bool cmp(const eg &a,const eg &b){return a.w<b.w;}
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int fa[N],val[N],f[N][20],bin[25],ls[N],rs[N],rt[N],ans[N],dep[N],rk[N],a[N],col[N],b[N];
int cnt,n,m,q,tim,Time,t,op,x,y,S,p,now,l,r,T,lim;
struct query{
int l,r,t,id,op;
inline bool operator <(const query &b)const{
return rt[l]!=rt[b.l]?l<b.l:rt[r]!=rt[b.r]?r<b.r:t<b.t;
}
}qaq[N];
struct change{int pos,now,las;}c[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void mission(int u){for(R int i=1;bin[i]<=n;++i)f[u][i]=f[f[u][i-1]][i-1];}
void dfs(int u){
// puts("QAQ");
mission(u);
if(u<=n)return (void)(ls[u]=rs[u]=++tim,rk[tim]=u);
ls[u]=inf,rs[u]=0;
go(u)dep[v]=dep[u]+1,dfs(v),cmin(ls[u],ls[v]),cmax(rs[u],rs[v]);
}
int get(int x,int y){
// printf("%d %d\n",f[x][0],f[y][0]);
if(dep[y]>dep[x])swap(x,y);
fd(i,18,0)if(dep[f[x][i]]>=dep[y])x=f[x][i];
if(x==y)return val[x];
fd(i,18,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return val[f[x][0]];
}
int ck(int x,int y){
fd(i,18,0)if(f[x][i]&&val[f[x][i]]<=y)x=f[x][i];
return x;
}
inline void revise(R int x,R int d){col[x]+=d;d>0?(now+=col[x]==1):(now-=col[x]==0);}
inline void going(R int x,R int d){if(x>=l&&x<=r)revise(d,1),revise(a[x],-1);a[x]=d;}
int main(){
// freopen("testdata.in","r",stdin);
cnt=n=read(),m=read(),q=read(),S=pow(n,0.666);
if(S==0)S=1;
bin[0]=1;fp(i,1,20)bin[i]=bin[i-1]<<1;
fp(i,1,(n<<1))fa[i]=i;
fp(i,1,n)b[++lim]=val[i]=read(),rt[i]=(i-1)/S+1;
fp(i,1,m)E[i].u=read(),E[i].v=read(),E[i].w=read();
// fp(i,1,m)printf("%d %d %d\n",E[i].u,E[i].v,E[i].w);
sort(E+1,E+1+m,cmp);
fp(i,1,m){
int u=find(E[i].u),v=find(E[i].v);
if(u!=v){
val[++cnt]=E[i].w,fa[u]=fa[v]=cnt;
add(cnt,u),add(cnt,v),f[u][0]=f[v][0]=cnt;
if(cnt-n==n-1)break;
}
}dfs(cnt);
fp(i,1,n)a[i]=val[rk[i]];
// fp(i,1,n)printf("%d %d\n",i,ls[i]);
fp(i,1,q){
op=read(),x=read(),y=read();
// printf("%d %d %d %d\n",i,op,x,y);
switch(op){
case 1:c[++Time]={ls[x],y,val[x]},b[++lim]=y,val[x]=y;break;
case 2:ans[++t]=x==y?0:get(x,y);break;
case 3:{
p=ck(x,y);
++t,qaq[t]={ls[p],rs[p],Time,t,1};
break;
}
}
}sort(qaq+1,qaq+1+t);
sort(b+1,b+1+lim),lim=unique(b+1,b+1+lim)-b-1;
fp(i,1,n)a[i]=lower_bound(b+1,b+1+lim,a[i])-b;
fp(i,1,Time){
c[i].las=lower_bound(b+1,b+1+lim,c[i].las)-b;
c[i].now=lower_bound(b+1,b+1+lim,c[i].now)-b;
}
l=1,r=0,T=0;
fp(i,1,t)if(qaq[i].op==1){
while(T<qaq[i].t)++T,going(c[T].pos,c[T].now);
while(T>qaq[i].t)going(c[T].pos,c[T].las),--T;
while(l>qaq[i].l)revise(a[--l],1);
while(r<qaq[i].r)revise(a[++r],1);
while(r>qaq[i].r)revise(a[r--],-1);
while(l<qaq[i].l)revise(a[l++],-1);
// printf("%d %d %d %d\n",qaq[i].id,qaq[i].l,qaq[i].r,qaq[i].t);
ans[qaq[i].id]=now;
}fp(i,1,t)print(ans[i]);
return Ot(),0;
}
P5168 xtq玩魔塔的更多相关文章
- P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]
P5168 xtq玩魔塔 又是码农题- 利用克鲁斯卡尔重构树的性质 我们就可以得出 \(dep\) 值小的,肯定比 \(dep\) 大的值要优. 于是第二问就可以直接 LCA 求出来了- 至于第三问, ...
- Luogu P5168 xtq玩魔塔
这题不错啊,结合了一些不太传统的姿势. 首先看到题目有一问从一个点到另一个点边权最小值.想到了什么? 克鲁斯卡尔生成树+倍增?好吧其实有一个更常用NB的算法叫克鲁斯卡尔重构树 (不会的可以看dalao ...
- 【Luogu P5168】xtq玩魔塔(Kruskal 重构树 & 树状数组 & set)
Description 给定一个 \(n\) 个顶点,\(m\) 条边的无向联通图,点.边带权. 先有 \(q\) 次修改或询问,每个指令形如 \(\text{opt}\ x\ y\): \(\tex ...
- SDUTOJ2465:其实玩游戏也得学程序(bfs+优先队列+回溯)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2465 题目描述 由于前两次的打击,ZYJ同学不 ...
- 这款打怪升级的小游戏,7 年前出生于 GitHub 社区,如今在谷歌商店有 8 万人打了满分
今天我在 GitHub 摸鱼寻找新的"目标"时,发现了一个开源项目是 RougeLike 类的角色扮演游戏「破碎版像素地牢」(Shattered Pixel Dungeon)类似魔 ...
- 2018-2019学年第一学期Java课设--魔塔
目录 Magic-Towers 一.团队名称.团队成员介绍.任务分配 团队名称:MoTa 团队成员介绍 任务分配 二.项目简介 三.项目采用技术 四.项目亮点 主界面显示主要信息功能 游戏动画 五.项 ...
- 自己做的roguelike+恶魔城游戏《魔塔猎人》已发布。
游戏仍然是标准的roguelike,死亡后回到出生点重新开始,宏观架构上参考了<死亡细胞>,战斗设计上更加强调轻重攻击的组合,再配合236和28系列的搓招技.空中的突进飞腿.副武器等等. ...
- 魔兽争霸war3心得体会(四):不死族vs人族1本火魔塔
QQ对战平台上玩随机的人特别多,为了应对对方的"出其不意",我最近一直用小狗去探路,小狗在家采集30个木头-摆放商店,就可以去探路了.主要有几个好处:知道对方的种族-出生点位-开局 ...
- 玩转spring boot——快速开始
开发环境: IED环境:Eclipse JDK版本:1.8 maven版本:3.3.9 一.创建一个spring boot的mcv web应用程序 打开Eclipse,新建Maven项目 选择quic ...
随机推荐
- 【iOS】系统框架学习
iOS的系统架构分为四个层次:核心操作系统层(Core OS layer).核心服务层(Core Services layer).媒体层(Media layer)和可触摸层(Cocoa Touch l ...
- 前端编程提高之旅(五)----写给大家看的css书
自实习也有几个月的时间了,以爱奇艺实习为敲门砖.进入了眼下这家公司.假设说当初能进爱奇艺是暂时袭击DIV+CSS的话,眼下在这家公司体验到.不论什么技术都必须悉知原理,这样才干做到庖丁解牛.做一 ...
- attribute constructor&destructor
attribute constructor&destructor 在看openwrt里libnl-tiny这个库的时候,遇到了C里面的构造函数这个概念. static void __init ...
- 【C语言】统计数字在排序数组中出现的次数
//数字在排序数组中出现的次数. //统计一个数字在排序数组中出现的次数.比如:排序数组{1,2,3,3,3,3,4,5}和数字3,因为3出现了4次,因此输出4. #include <stdio ...
- Devices下设备的进程显示为问号的问题
adb shell getprop ro.debuggable 返回 ro.debuggable=0 说明这个机子的版本不是userdebug版本,是user版本 只有这 ...
- Printf可变參数使用
參考文档: http://bbs.csdn.net/topics/70288067 Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源 本文的二 ...
- Hibernate中的merge使用详情解说
merge的作用是:新new一个对象,如果该对象设置了ID,则这个对象就当作游离态处理: 当ID在数据库中不能找到时,用up ...
- 记录001:AS11 BAPI
未知元素(174657434) 15:05:41AS11有没有BAPI呀?有做过的吗 BAPI_FIXEDASSET_OVRTAKE_CREATE
- code::Blocks 汉化经验
首先,在网上下载一个code::Block的汉化包 code::Block汉化包下载地址,复制到地址栏即可. http://files.cnblogs.com/files/QW-lzm/codebl ...
- codeforces A. Kitahara Haruki's Gift 解题报告
题目链接:http://codeforces.com/problemset/problem/433/A 题目意思:给定 n 个只由100和200组成的数,问能不能分成均等的两份. 题目其实不难,要考虑 ...