3083: 遥远的国度

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 797  Solved: 181
[Submit][Status]

Description

描述
zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成
了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有
一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的
话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但
zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

Input

第1行两个整数n m,代表城市个数和操作数。
第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
第n+1行,有n个整数,代表所有点的初始防御值。
第n+2行一个整数 id,代表初始的首都为id。
第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数
p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数
id,代表询问以城市id为根的子树中的最小防御值。

Output

对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

Sample Input

3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1

Sample Output

1
2
3
4
提示
对于20%的数据,n<=1000 m<=1000。
对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。
 
 
 

思路来自hja,劲爆的读入优化来自zhonghaoxi,基本自己没想什么,还Wa了很久。

主要就是树链剖分。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cctype>
  6. using namespace std;
  7. #define INF 0x3f3f3f3f
  8. #define MAXN 110000
  9. #define lch (now<<1)
  10. #define rch (now<<1^1)
  11. typedef long long qword;
  12. #ifdef unix
  13. #define LL "%d"
  14. #else
  15. #define LL "%I64d"
  16. #endif
  17.  
  18. const int BUF_SIZE = ;
  19. char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + ;
  20. #define PTR_NEXT() \
  21. { \
  22. buf_s ++; \
  23. if (buf_s == buf_t) \
  24. { \
  25. buf_s = buf; \
  26. buf_t = buf + fread(buf, , BUF_SIZE, stdin); \
  27. } \
  28. }
  29.  
  30. #define readint(_n_) \
  31. { \
  32. while (*buf_s != '-' && !isdigit(*buf_s)) \
  33. PTR_NEXT(); \
  34. bool register _nega_ = false; \
  35. if (*buf_s == '-') \
  36. { \
  37. _nega_ = true; \
  38. PTR_NEXT(); \
  39. } \
  40. int register _x_ = ; \
  41. while (isdigit(*buf_s)) \
  42. { \
  43. _x_ = _x_ * + *buf_s - ''; \
  44. PTR_NEXT(); \
  45. } \
  46. if (_nega_) \
  47. _x_ = -_x_; \
  48. (_n_) = (_x_); \
  49. }
  50. int n,m;
  51. int val_t[MAXN];
  52. //segment_tree{{{
  53. struct segt
  54. {
  55. int l,r,val;
  56. int tag;
  57. }tree[MAXN*];
  58. int ptr[MAXN];
  59. void down(int now)
  60. {
  61. if (tree[now].tag!=INF)
  62. {
  63. tree[lch].val=tree[rch].val=tree[lch].tag=tree[rch].tag=tree[now].tag;
  64. tree[now].tag=INF;
  65. }
  66. }
  67. void update(int now)
  68. {
  69. if (tree[now].l==tree[now].r)return ;
  70. tree[now].val=min(tree[lch].val,tree[rch].val);
  71. }
  72. void build_tree(int now,int l,int r)
  73. {
  74. tree[now].l=l;
  75. tree[now].r=r;
  76. tree[now].tag=INF;
  77. if (l==r){
  78. ptr[l]=now;
  79. tree[now].val=val_t[l];
  80. return;
  81. }
  82. int mid=(l+r)>>;
  83. build_tree(lch,l,mid);
  84. build_tree(rch,mid+,r);
  85. update(now);
  86. }
  87. /*
  88. void set_val(int pos,int val)
  89. {
  90. pos=ptr[pos];
  91. tree[pos].val=val;
  92. while (pos)
  93. {
  94. update(pos);
  95. pos>>=1;
  96. }
  97. }*/
  98. void set_seg(int now,int l,int r,int val)
  99. {
  100. down(now);
  101. if (tree[now].l==l&&tree[now].r==r)
  102. {
  103. tree[now].val=val;
  104. tree[now].tag=val;
  105. return ;
  106. }
  107. int mid=(tree[now].l+tree[now].r)>>;
  108. if (r<=mid)
  109. {
  110. set_seg(lch,l,r,val);
  111. update(now);
  112. return ;
  113. }
  114. if (mid<l)
  115. {
  116. set_seg(rch,l,r,val);
  117. update(now);
  118. return ;
  119. }
  120. set_seg(lch,l,mid,val);
  121. set_seg(rch,mid+,r,val);
  122. update(now);
  123.  
  124. }
  125. int query_min(int now,int l,int r)
  126. {
  127. down(now);
  128. if (tree[now].l==l&&tree[now].r==r)
  129. {
  130. return tree[now].val;
  131. }
  132. int mid;
  133. mid=(tree[now].l+tree[now].r)>>;
  134. if (r<=mid)
  135. {
  136. return query_min(lch,l,r);
  137. }
  138. if (mid<l)
  139. {
  140. return query_min(rch,l,r);
  141. }
  142. return min(query_min(lch,l,mid),query_min(rch,mid+,r));
  143. }
  144. //}}}
  145. struct Edge
  146. {
  147. int np;
  148. Edge *next;
  149. }E[MAXN*],*V[MAXN];
  150. int root,tope=-;
  151. void addedge(int x,int y)
  152. {
  153. E[++tope].np=y;
  154. E[tope].next=V[x];
  155. V[x]=&E[tope];
  156. }
  157. int dfn[MAXN],l[MAXN],fa[MAXN],inp[MAXN],oup[MAXN];
  158. int depth[MAXN];
  159. int cnt=;
  160. int siz_s[MAXN],son[MAXN];
  161. int siz_t[MAXN];
  162. int top[MAXN];
  163. int dfs(int now,int dep)
  164. {
  165. Edge *ne;
  166. int t;
  167. siz_s[now]=;
  168. siz_t[now]=;
  169. depth[now]=dep;
  170. for (ne=V[now];ne;ne=ne->next)
  171. {
  172. if (fa[now]!=ne->np)
  173. {
  174. fa[ne->np]=now;
  175. t=dfs(ne->np,dep+);
  176. siz_t[now]+=t;
  177. if (t>siz_s[now])
  178. {
  179. siz_s[now]=t;
  180. son[now]=ne->np;
  181. }
  182. }
  183. }
  184. return siz_t[now];
  185. }
  186. void dfs2(int now,int tp)
  187. {
  188. Edge *ne;
  189. dfn[now]=++cnt;
  190. inp[now]=cnt;
  191. l[cnt]=val_t[now];
  192. top[now]=tp;
  193. if (son[now])dfs2(son[now],tp);
  194. for (ne=V[now];ne;ne=ne->next)
  195. {
  196. if (fa[now]!=ne->np&&son[now]!=ne->np)
  197. {
  198. dfs2(ne->np,ne->np);
  199. }
  200. }
  201. oup[now]=cnt;
  202. }
  203. int jump[][MAXN],topj;
  204. void init_lca()
  205. {
  206. int i,j;
  207. for (i=;i<=n;i++)jump[][i]=fa[i];
  208. bool flag=true;
  209. for (i=;i<&&flag;i++)
  210. {
  211. flag=false;
  212. topj=i;
  213. for (j=;j<=n;j++)
  214. {
  215. jump[i][j]=jump[i-][jump[i-][j]];
  216. if (jump[i][j]!=root)flag=true;
  217. }
  218. }
  219. }
  220. void swim(int &x,int l)
  221. {
  222. int i=;
  223. while (l)
  224. {
  225. if (l&)x=jump[i][x];
  226. i++;
  227. l>>=;
  228. }
  229. }
  230. int lca(int x,int y)
  231. {
  232. if (depth[x]<depth[y])
  233. {
  234. swim(y,depth[y]-depth[x]);
  235. }
  236. if (depth[x]>depth[y])
  237. {
  238. swim(x,depth[x]-depth[y]);
  239. }
  240. if (x==y)return x;
  241. for (int i=topj;i>=;i--)
  242. {
  243. if (jump[i][x]!=jump[i][y])
  244. {
  245. x=jump[i][x];
  246. y=jump[i][y];
  247. }
  248. }
  249. return fa[x];
  250. }
  251. int id;
  252. int main()
  253. {
  254. freopen("input.txt","r",stdin);
  255. //freopen("output2.txt","w",stdout);
  256. //scanf("%d%d",&n,&m);
  257. readint(n);
  258. readint(m);
  259. int i,j,k,x,y,z;
  260. int a;
  261. for (i=;i<n;i++)
  262. {
  263. //scanf("%d%d",&x,&y);
  264. readint(x);
  265. readint(y);
  266. addedge(x,y);
  267. addedge(y,x);
  268. }
  269. root=;
  270. fa[root]=root;
  271. dfs(root,);
  272. dfs2(root,root);
  273. init_lca();
  274. for (i=;i<=n;i++)
  275. {
  276. readint(x);
  277. //scanf("%d",&x);
  278. val_t[dfn[i]]=x;
  279. }
  280. build_tree(,,cnt);
  281. readint(id);
  282. //scanf("%d",&id);
  283. int opt,ans;
  284. //cout<<"a";
  285. for (i=;i<m;i++)
  286. {
  287. //scanf("%d",&opt);
  288. readint(opt);
  289. if (opt==)
  290. {
  291. //scanf("%d",&id);
  292. readint(id);
  293. }
  294. if (opt==)
  295. {
  296. //scanf("%d%d%d",&x,&y,&z);
  297. readint(x);
  298. readint(y);
  299. readint(z);
  300. while (top[x]!=top[y])
  301. {
  302. if (depth[top[x]]<depth[top[y]])swap(x,y);
  303. set_seg(,dfn[top[x]],dfn[x],z);
  304. x=fa[top[x]];
  305. }
  306. if (dfn[x]<dfn[y])
  307. {
  308. set_seg(,dfn[x],dfn[y],z);
  309. }else
  310. {
  311. set_seg(,dfn[y],dfn[x],z);
  312. }
  313. }
  314. if (opt==)
  315. {
  316. //scanf("%d",&x);
  317. readint(x);
  318. if (x==id)
  319. {
  320. ans=query_min(,,n);
  321. printf("%d\n",ans);
  322. continue;
  323. }
  324. if (x==root)
  325. {
  326. LABEL2:
  327. y=id;
  328. /* for (j=topj;j>=0;j--)
  329. {
  330. if (jump[j][y]!=x)
  331. {
  332. y=jump[j][y];
  333. }
  334. }*/
  335. swim(y,depth[y]-depth[x]-);
  336. ans=INF;
  337. if (inp[y]!=)ans=query_min(,,inp[y]-);
  338. if (oup[y]!=n)ans=min(ans,query_min(,oup[y]+,n));
  339. printf("%d\n",ans);
  340. continue;
  341. }
  342. if (depth[x]>=depth[id])
  343. {
  344. LABEL1:
  345. ans=query_min(,inp[x],oup[x]);
  346. printf("%d\n",ans);
  347. continue;
  348. }
  349. if (lca(x,id)==x)
  350. {
  351. /* ans=INF;
  352. ans=query_min(1,1,inp[x]);
  353. if (oup[x]!=n)ans=min(ans,query_min(1,oup[x]+1,n));
  354. printf("%d\n",ans);*/
  355. goto LABEL2;
  356. continue;
  357. }else
  358. {
  359. goto LABEL1;
  360. }
  361. }
  362. // cout<<opt<<" "<<x<<" "<<y<<endl;
  363. }
  364.  
  365. }

BZOJ 3083 遥远的国度 树链剖分的更多相关文章

  1. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  2. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  3. BZOJ 3083 遥远的国度 树链剖分+线段树

    有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...

  4. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  5. bzoj 3083 遥远的国度 —— 树链剖分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 换根后路径还是不变,子树分类讨论一下,树剖后线段树维护即可. 代码如下: #inclu ...

  6. bzoj 3083 遥远的国度——树链剖分+线段树维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 int 的范围是 2^31 - 1 ,所以权值是不是爆 int 了…… O( nlog ...

  7. BZOJ 3083 遥远的国度 树链剖分+脑子

    唉..又调了半天QWQ..为何读入挂了.....莫非读入是反着的????据ywy学长所言如是...OvO震惊 这啥骚题啊...还要换根...不过清明讲过...(然鹅我现在才做... 先随便选个点(比如 ...

  8. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  9. 【bzoj3083】遥远的国度 树链剖分+线段树

    题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...

随机推荐

  1. mysql in 的两种使用方法

    简述MySQL 的in 的两种使用方法: 他们各自是在 in keyword后跟一张表(记录集).以及在in后面加上字符串集. 先讲后面跟着一张表的. 首先阐述三张表的结构: s(sno,sname. ...

  2. GCC 编绎选项 转

    gcc提供了大量的警告选项,对代码中可能存在的问题提出警告,通常可以使用-Wall来开启以下警告:           -Waddress -Warray-bounds (only with -O2) ...

  3. vc++ 最小化到托盘的详细实现

    在VC++中,想实现将MFC最小化到系统托盘,需要调用NOTIFYICONDATA类,并注册相应的消息,以下详细讲解如何实现: 1.声明一个NOTIFYICONDATA类,也就是NOTIFYICOND ...

  4. UTF-8 BOM对PHP的影响

    今天在用notepad++写代码时 载入一个frameset框架模版后 在页面上一直不显示该页面,查看源码后都正常.然后索性把里面东西全删掉 随便写了几个测试文字可以正常显示. 折腾了好长时间,最后偶 ...

  5. ASP.NET+ashx+jQuery动态添加删除表格

    aspx: <script src="../script/jquery-1.4.4.min.js" type="text/javascript" lang ...

  6. mysql开启函数功能

    输入 show variables like '%func%'; 命令 会看到 log_bin_trust_function_creators 的状态,如果是OFF表示自定义函数功能是关闭的 输入命令 ...

  7. MES项目中出现的一个事务嵌套的使用场景

    昨天在MES项目中,需要在业务逻辑的几个关键点记录错误信息,需要把错误信息写入数据表. 但是由于整个业务逻辑都是包在一个事务模板里面的 比如这样的: WhhTransactionTemplate tr ...

  8. Android Studio SDK Manager无法正常下载如何设置

    博客分类: Linux 零散小知识 Android那点事 AndroidStudioSDKManager  一方面在/etc/hosts中设置: #Google主页 203.208.46.146 ww ...

  9. 深入理解自定义ListView

    深入理解自定义ListView ListView原理 他是一个系统的原生控件,用列表的形式来显示内容.如果内容过过有1000条左右,我们可以通过手势的上下滑动来查看数据.ListView也不是爆出OO ...

  10. 'EntityValidationErrors' property for more details

    很多小猿遇到这个Exception 的时候,都会有点无厘头.这个时候最好try-- catch下,找到出错的地方.本人习惯在页面上加个lable标签,把exc msg(exception messag ...