题目:

Description

在一片古老的土地上,有一个繁荣的文明。
这片大地几乎被森林覆盖,有N座城坐落其中。巧合的是,这N座城由恰好N-1条双
向道路连接起来,使得任意两座城都是连通的。也就是说,这些城形成了树的结构,任意两
座城之间有且仅有一条简单路径。
在这个文明中,骑士是尤其受到尊崇的职业。任何一名骑士,都是其家族乃至家乡的荣
耀。Henry从小就渴望成为一名能守护家乡、驱逐敌人的骑士。勤奋训练许多年后,Henry
终于满18岁了。他决定离开家乡,向那些成名已久的骑士们发起挑战!
根据Henry的调查,大陆上一共有M名受封骑士,不妨编号为1到M。
第i个骑士居住在城Pi,武力值为Fi。
Henry计划进行若干次旅行,每次从某座城出发沿着唯一的简单路径前往另一座城,
同时会挑战路线上武力值最高的K个骑士(Henry的体力有限,为了提高水平,当然要挑
战最强的骑士)。如果路线上的骑士不足K人,Henry会挑战遇到的所有人。
每次旅行前,可能会有某些骑士的武力值或定居地发生变化,Henry自然会打听消息,
并对计划做出调整。
为了在每次旅行时做好充分准备,Henry希望你能帮忙在每次旅行前计算出这条路线
上他将挑战哪些对手。

Input

第一行,一个整数N,表示有N座城,编号为1~N。
接下来N-1行,每行两个整数Ui和Vi,表示城Ui和城Vi之间有一条道路相连。
第N+1行,一个整数M,表示有M个骑士。
接下来M行,每行两个整数Fi和Pi。按顺序依次表示编号为1~M的每名骑士的武
力值和居住地。
第N+M+2行,两个整数Q,K,分别表示操作次数和每次旅行挑战的骑士数目上限。
接下来Q行,每行三个整数Ti,Xi,Yi。Ti取值范围为{1,2,3},表示操作类型。
一共有以下三种类型的操作:
Ti=1时表示一次旅行,Henry将从城Xi出发前往城市Yi;
Ti=2时表示编号为Xi的骑士的居住地搬到城Yi;
Ti=3时表示编号为Xi的骑士的武力值修正为Yi。

Output

输出若干行,依次为每个旅行的答案。
对每个Ti=1的询问,输出一行,按从大到小的顺序输出Henry在这次旅行中挑战的
所有骑士的武力值。如果路线上没有骑士,输出一行,为一个整数-1。

Sample Input

5
1 2
1 3
2 4
2 5
4
10 1
6 1
14 5
7 3
5 3
1 2 3
1 5 3
1 4 4
2 1 4
1 2 3

Sample Output

10 7 6
14 10 7
-1
7 6

Hint

100%的数据中,1 ≤ N, M ≤ 40,000,1 ≤ Ui, Vi, Pi ≤ N,1 ≤ Q ≤ 80,000, 1 ≤ K ≤ 
20,旅行次数不超过 40,000 次,武力值为不超过1,000的正整数。 

题解:

先树链剖分····然后树链剖分的每一个树上套上一颗权值线段树····

我的方法有点暴力···要输入前K大直接一个一个找·····所以慢得飞起·····

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int N=4e5+;
const int M=4e7+;
struct node
{
int size,l,r;
}tr[M];
int n,m,q,K;
int tot,fst[N],nxt[N*],go[N*],f[N],p[N],root[N*],loc[N*],cnt,sum[N*],temp,que[N*];
int father[N],deep[N],son[N],size[N],pos[N],idx[N],top[N];
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
inline void comb(int a,int b)
{
nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b;
nxt[++tot]=fst[b],fst[b]=tot,go[tot]=a;
}
inline void dfs1(int u)
{
size[u]=;
for(int e=fst[u];e;e=nxt[e])
{
int v=go[e];if(v==father[u]) continue;
father[v]=u;deep[v]=deep[u]+;
dfs1(v);size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
inline void dfs2(int u)
{
if(son[u])
{
idx[pos[son[u]]=++tot]=son[u];
top[son[u]]=top[u];dfs2(son[u]);
}
for(int e=fst[u];e;e=nxt[e])
{
int v=go[e];if(v==father[u]||v==son[u]) continue;
idx[pos[v]=++tot]=v;
top[v]=v;dfs2(v);
}
}
inline void pre()
{
dfs1();
tot=pos[]=idx[]=top[]=;
dfs2();
}
inline void modify2(int &k,int l,int r,int v)
{
if(!k) k=++tot;tr[k].size++;
if(l==r) return;
int mid=(l+r)/;
if(v<=mid) modify2(tr[k].l,l,mid,v);
else modify2(tr[k].r,mid+,r,v);
}
inline void delete2(int k,int l,int r,int v)
{
tr[k].size--;
if(l==r) return;
int mid=(l+r)/;
if(v<=mid) delete2(tr[k].l,l,mid,v);
else delete2(tr[k].r,mid+,r,v);
}
inline void modify1(int k,int l,int r,int p,int v)
{
sum[k]++;
modify2(root[k],,,v);
if(l==r) return;
int mid=(l+r)/;
if(p<=mid) modify1(k*,l,mid,p,v);
else modify1(k*+,mid+,r,p,v);
}
inline void delete1(int k,int l,int r,int p,int v)
{
sum[k]--;
delete2(root[k],,,v);
if(l==r) return;
int mid=(l+r)/;
if(p<=mid) delete1(k*,l,mid,p,v);
else delete1(k*+,mid+,r,p,v);
}
inline void getroot2(int k,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
que[++cnt]=root[k];temp+=sum[k];
return;
}
int mid=(l+r)/;
if(x<=mid) getroot2(k*,l,mid,x,y);
if(y>mid) getroot2(k*+,mid+,r,x,y);
}
inline void getroot1(int a,int b)
{
if(top[a]!=top[b])
{
if(deep[top[a]]<deep[top[b]]) swap(a,b);
getroot2(,,n,pos[top[a]],pos[a]);
getroot1(father[top[a]],b);
}
else
{
if(deep[a]<deep[b]) swap(a,b);
getroot2(,,n,pos[b],pos[a]);
}
}
inline int calc()
{
int t=;
for(int i=;i<=cnt;i++) t+=tr[tr[loc[i]].l].size;
return t;
}
inline void trans(int op)
{
if(!op)
for(int i=;i<=cnt;i++) loc[i]=tr[loc[i]].l;
else
for(int i=;i<=cnt;i++) loc[i]=tr[loc[i]].r;
}
inline int query(int l,int r,int k)
{
if(l==r) return l;
int t=calc();int mid=(l+r)/;
if(t>=k)
{
trans();
return query(l,mid,k);
}
else
{
trans();
return query(mid+,r,k-t);
}
}
int main()
{
n=R();int a,b,op;
for(int i=;i<n;i++)
{
a=R(),b=R();
comb(a,b);
}
pre();
m=R();tot=;
for(int i=;i<=m;i++)
{
f[i]=R(),p[i]=R();
modify1(,,n,pos[p[i]],f[i]);
}
q=R(),K=R();
while(q--)
{
op=R(),a=R(),b=R();
if(op==)
{
temp=cnt=;
getroot1(a,b);
if(!temp) printf("-1");
if(temp<=K)
{
for(int i=temp;i>=;i--)
{
for(int j=;j<=cnt;j++) loc[j]=que[j];
printf("%d ",query(,,i));
}
}
else
{
for(int i=temp;i>=temp-K+;i--)
{
for(int j=;j<=cnt;j++) loc[j]=que[j];
printf("%d ",query(,,i));
}
}
printf("\n");
}
else if(op==)
{
delete1(,,n,pos[p[a]],f[a]);
p[a]=b;
modify1(,,n,pos[p[a]],f[a]);
}
else if(op==)
{
delete1(,,n,pos[p[a]],f[a]);
f[a]=b;
modify1(,,n,pos[p[a]],f[a]);
}
}
}

刷题总结——骑士的旅行(bzoj4336 树链剖分套权值线段树)的更多相关文章

  1. luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

    带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...

  2. CF1093E Intersection of Permutations 树状数组套权值线段树

    \(\color{#0066ff}{ 题目描述 }\) 给定整数 \(n\) 和两个 \(1,\dots,n\) 的排列 \(a,b\). \(m\) 个操作,操作有两种: \(1\ l_a\ r_a ...

  3. Dynamic Rankings(树状数组套权值线段树)

    Dynamic Rankings(树状数组套权值线段树) 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[ ...

  4. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

  5. BZOJ2141排队——树状数组套权值线段树(带修改的主席树)

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...

  6. 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

    谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...

  7. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  8. Qtree3题解(树链剖分(伪)+线段树+set)

    外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意: 很明显吧.. 题解: 我的做法十分的暴力:树链剖分(伪)+线段树+\(set\)... ...

  9. Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树)

    Luogu 2590 [ZJOI2008]树的统计 / HYSBZ 1036 [ZJOI2008]树的统计Count (树链剖分,LCA,线段树) Description 一棵树上有n个节点,编号分别 ...

随机推荐

  1. UVA 12901 Refraction 折射 (物理)

    一道物理题,解个2次方程就行了... 求h最小的情况对应如下图所示 做法不唯一,我想避免精度损失所以在化简的时候尽可能地去避免sqrt和浮点数乘除. 似乎精度要求很低,直接用角度算也可以 #inclu ...

  2. (原)IPhone开发时把ToolBar中的元素居中的技巧

    在IPhone应用开发时,经常用到ToolBar,其中的控件通常都是居左,想让它居中就有点困难. 这里介绍一种方法: 将Flexible Space Bar Button Item从库中拖到位于控件左 ...

  3. 2018.3.16 Ubuntu 解决中文乱码问题

    一.乱码的样子类似: °²Àï¿ü ÒÁ¸ñÀ³Ï£ÑÇ˹,°²Àï¿ü ÒÁ¸ñÀ³Ï£ÑÇ˹ 这种乱码称为Gedit中文乱码 打开部分Windows下的txt文本文件的时候,中文显示为乱码.但 ...

  4. 字符编码:WideCharToMultiByte

    WideCharToMultiByte 编辑   目录 1基本介绍及功能 2相关变量     1基本介绍及功能编辑 WideCharToMultiByte 函数功能:该函数映射一个unicode字符串 ...

  5. c++作业:使用函数调用的方法,实现求两个整数中大的数的程序。

    #include <iostream> using namespace std; int main(){ //从键盘接收两个整数,保存在变量num1和num2中 cout<<& ...

  6. B. Anatoly and Cockroaches

    B. Anatoly and Cockroaches time limit per test 1 second memory limit per test 256 megabytes input st ...

  7. 【线性基合并 树链剖分】bzoj4568: [Scoi2016]幸运数字

    板子题 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市 ...

  8. pycharm安装 suds模块报错:AttributeError: module 'pip' has no attribute 'main'

    需求:安装suds模块 遇到的问题: 一.报错信息:[file][Default Settint]---Project Interpreter 点击 搜索suds安装模块报错 解决:依据上图提示找到C ...

  9. SSH框架面试总结----1

    1:struts2的工作流程 1)客户端浏览器发出HTTP请求. 2)根据web.xml配置,HTTP请求会被FilterDispatcher接收. 3)根据struts.xml,找到对应的Actio ...

  10. 局域网映射到公网-natapp实现

    在开发时可能会有这样的需求: 需要将自己开发的机器上的应用提供到公网上进行访问,但是并不想通过注册域名.搭建服务器等等一系列繁琐的操作来实现. 例如:微信公众号的开发调试就需要用到域名访问本机项目. ...