2017/11/08 胡策 T3

一个长为 n 的链,点权分别为 1 ~ n,最左边的点权为 n,最右边的点权为 1,每个点分别向左边和右边第一个比它大的点连长为 1 的无向边,问任意两点的最短路径。1 <= n <= 100000。

  考虑连边的性质,两点的最短路径一定是点权递增或先增后减,所以相当于由点权小的向点权大的连有向边,每次询问时两点同时往上跳,跳到同一个点终止。设向左连的边构成左树,向右连的构成右树,则两点可能的终点只有三个:左树 lca、右树 lca、左树和右树到根路径的交点(即两点所夹区间最大值的位置)。

  考虑怎样用倍增来解决,利用每个点向第一个比它大的点连边的性质,若 x 的目标结点是 y,x 连接的两个点分别为 a 和 b,且 x < a < b < y,则跳 b 肯定比跳 a 优,所以可以使每个点向它两条边中较大点连边建出优势树,在优势树上倍增,跳到下一个点就要大于 y 时停止,可利用性质证明这时剩下的边一定是都在左树或都在右树上,直接用深度相减得出答案。

  例如序列:

10 8 4 3 2 5 6 7 9 1

  蓝边表示左树,紫边表示右树:

  红边表示优势树:

  1 #include <bits/stdc++.h>
  2
  3 #define x first
  4 #define y second
  5 #define pb push_back
  6 #define mp make_pair
  7 #define vi vector<int>
  8 #define pr pair<int,int>
  9 #define SZ(S) int(S.size())
 10 #define REP(i,a,b) for(int i=a;i<b;++i)
 11 #define FOR(i,a,b) for(int i=a;i<=b;++i)
 12 #define FORD(i,b,a) for(int i=b;i>=a;--i)
 13 #define CLR(A,x) memset(A,x,sizeof(A))
 14 #define ALL(S) S.begin(),S.end()
 15
 16 #define OUT(a,l,r) cout<<#a": ";FOR(i,l,r)cout<<a[i]<<" ";cout<<endl
 17 #define PRT(a) cout<<"--> "#a" "<<a<<endl
 18
 19 using namespace std;
 20 typedef long long ll;
 21
 22 const int N=100005,M=18,INF=0x3f3f3f3f;
 23 const ll P=1e9+7;
 24
 25 template<typename T>
 26 inline void read(T& x,int f=1,char s=getchar()) {
 27     for(x=0;s>‘9‘||s<‘0‘;s=getchar()) if(s==‘-‘) f=-1;
 28     while(s<=‘9‘&&s>=‘0‘) x=x*10+s-‘0‘,s=getchar();x*=f;
 29 }
 30
 31 set<int> s;
 32 int n,m;
 33 int t[N<<2];
 34 int l[N],r[N];
 35 int a[N],rk[N];
 36 int depl[N],depr[N];
 37 int f[N][M];
 38
 39 #define ne (o<<1)
 40 #define mid ((l+r)>>1)
 41 void build(int o,int l,int r) {
 42     if(l==r) {t[o]=a[l];return;}
 43     build(ne,l,mid),build(ne|1,mid+1,r);
 44     t[o]=max(t[ne],t[ne|1]);
 45 }
 46
 47 int qmax(int o,int l,int r,int L,int R,int ret=0) {
 48     if(L<=l&&r<=R) return t[o];
 49     if(L<=mid) ret=max(ret,qmax(ne,l,mid,L,R));
 50     if(R>mid) ret=max(ret,qmax(ne|1,mid+1,r,L,R));
 51     return ret;
 52 }
 53
 54 #define IT set<int>::iterator
 55 void pre() {
 56     s.insert(1),s.insert(n);
 57     FORD(i,n-2,1) {
 58         int x=rk[i];
 59         IT it=s.insert(x).x;
 60         IT it1=it;it1--;
 61         IT it2=it;it2++;
 62         l[x]=*it1;
 63         r[x]=*it2;
 64     }
 65     l[n]=1;
 66     FOR(i,1,n) depl[i]=depl[l[i]]+1;
 67     FORD(i,n,1) depr[i]=depr[r[i]]+1;
 68     FORD(i,n-2,1) {
 69         int x=rk[i];
 70         if(a[l[x]]>=a[r[x]]) f[x][0]=l[x];
 71         else f[x][0]=r[x];
 72         REP(j,1,M) f[x][j]=f[f[x][j-1]][j-1];
 73     }
 74     f[n][0]=1;
 75 }
 76
 77 int dis(int x,int y,int *l,int *dep) {
 78     if(x==y) return 0;
 79     if(l[x]==y) return 1;
 80
 81     int ret=0;
 82     FORD(i,M-1,0) {
 83         int xx=f[x][i];
 84         if(xx==0) continue;
 85         if(xx==y) return ret+(1<<i);
 86         if(l[xx]==y) return ret+(1<<i)+1;
 87         if(dep[y]<dep[l[xx]]) x=xx,ret+=(1<<i);
 88     }
 89     return INF;
 90 }
 91
 92 int main() {
 93     int x,y,z;
 94     read(n),read(m);
 95     FOR(i,1,n) read(a[i]),rk[a[i]]=i;
 96     build(1,1,n);
 97     pre();
 98     FOR(i,1,m) {
 99         read(x),read(y);
100         int ans=INF;
101         z=rk[qmax(1,1,n,x,y)];
102         ans=min(ans,dis(x,z,r,depr)+dis(y,z,l,depl));
103
104         if(l[z]) ans=min(ans,dis(x,l[z],l,depl)+dis(y,l[z],l,depl));
105         if(r[z]) ans=min(ans,dis(x,r[z],r,depr)+dis(y,r[z],r,depr));
106         printf("%d\n",ans);
107     }
108     return 0;
109 }

std

极限数据生成:随机一个排列,分成大概20段,每段内排序。

 1 #include <bits/stdc++.h>
 2
 3 #define x first
 4 #define y second
 5 #define pb push_back
 6 #define mp make_pair
 7 #define vi vector<int>
 8 #define pr pair<int,int>
 9 #define SZ(S) int(S.size())
10 #define REP(i,a,b) for(int i=a;i<b;++i)
11 #define FOR(i,a,b) for(int i=a;i<=b;++i)
12 #define FORD(i,b,a) for(int i=b;i>=a;--i)
13 #define CLR(A,x) memset(A,x,sizeof(A))
14 #define ALL(S) S.begin(),S.end()
15
16 #define OUT(a,l,r) cout<<#a": ";FOR(i,l,r)cout<<a[i]<<" ";cout<<endl
17 #define PRT(a) cout<<"--> "#a" "<<a<<endl
18
19 using namespace std;
20 typedef long long ll;
21
22 const int N=100005,M=20,INF=0x3f3f3f3f;
23 const ll P=1e9+7;
24
25 template<typename T>
26 inline void read(T& x,int f=1,char s=getchar()) {
27     for(x=0;s>‘9‘||s<‘0‘;s=getchar()) if(s==‘-‘) f=-1;
28     while(s<=‘9‘&&s>=‘0‘) x=x*10+s-‘0‘,s=getchar();x*=f;
29 }
30
31 string pro="";
32 void add(string& s,int id) {
33     if(id>=10) {
34         s+=char(id/10+‘0‘);
35         s+=char(id%10+‘0‘);
36     }
37     else {
38         s+=char(id+‘0‘);
39     }
40 }
41
42 void gen_i(int id) {
43     string str="data.exe > data\\";
44     str+=pro;
45     add(str,id);
46     str+=".in";
47     cout<<str<<endl;
48     system(str.c_str());
49 }
50
51 void gen_o(int id) {
52     string str="std.exe < data\\";
53     str+=pro;
54     add(str,id);
55     str+=".in > data\\";
56     str+=pro;
57     add(str,id);
58     str+=".out";
59     cout<<str<<endl;
60     system(str.c_str());
61 }
62
63 int main() {
64     int l=1;
65     int r=10;
66
67     FOR(i,l,r) gen_i(i);
68     FOR(i,l,r) gen_o(i);
69 }

data


出题人:ISA

原文地址:https://www.cnblogs.com/milky-w/p/9038365.html

时间: 2024-08-02 17:56:33

2017/11/08 胡策 T3的相关文章

树的dfs序,p1539,其他经典问题,2018/11/08模拟赛T3

树的dfs序指从根节点进行dfs(先序遍历),每次到达某个点的时间和离开这个点的时间.它可以将树上的问题转换成序列问题进行处理. 比如对于p1539的样例可以这样解释. 每个点的左边数字表示进入该点的"时间",右边的数字表示离开该点的"时间".对dfs序的介绍就到这里. 然后来看一个例题: 先读入边,跑一遍dfs确定dfs序. 对于操作1,把点x的进入的"时间"+=a,把x出去的"时间"-=a 这样操作3询问根节点到y的路径点

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

2017.11.25【NOIP提高组】模拟赛A组

2017.11.25[NOIP提高组]模拟赛A组 T1 3467. [NOIP2013模拟联考7]最长上升子序列(lis) T2 3468. [NOIP2013模拟联考7]OSU!(osu) T3 3472. [NOIP2013模拟联考8]匹配(match) T1 有转移方程f[i]=max{f[j]}+1,a[j]<a[i] 可以用线段树+离散化维护这个方程,因为涉及以往状态可以用主席树维护 打太丑爆空间了 Code 1 #include<cstdio> 2 #include<c

弱省胡策系列简要题解

现在不是非常爽,感觉智商掉没了,就整理一下最近弱省胡策的题目吧. 其实题目质量还是很高的. 如果实在看不懂官方题解,说不定这里bb的能给您一些帮助呢? [弱省胡策]Round #0 A 20%数据,O(n4)傻逼dp. 40%数据,O(n3)傻逼dp. 100%数据,令f(x1,y1,x2,y2)表示从(x1,y1)走到(x2,y2)的路径条数.于是所有路径就是f(1,2,n?1,m)×f(2,1,n,m?1).然而两条路径可能在中间的某个点相交,我们找出最早的交点,并在这个交点互换两条路径的后

使用 VS2013 Update 4 编译 NASM 2.11.08

1. 下载 nasm-2.11.08.zip (here/here) 解压至本地 2. 开始 -> Visual Studio 2013 -> Visual Studio 2013 Tools -> Developer Command Prompt for VS2013 cd 到 NASM 所在路径 参照 Mkfiles\README,执行 nmake /f Mkfiles/msvc.mak 3. 编译成功 完整编译包,如需减小exe大小,可在 makefile 中加上 compiler

2017/11/07_那么明显的坑你还往里跳 Cannot set property &#39;innerHTML&#39; of null

学习react,使用webpack构建工具 在html引入生成的bundle.js时,写成了这样子: 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script src="bundle.js"></scri

2017.11.15 String、StringBuffer、StringBuilder的比较

参考来自:http://blog.csdn.net/jeffleo/article/details/52194433 1.速度 一般来说,三者的速度是:StringBuilder > StringBuffer > String. 但是,在String a = "how" + "old" + "are" + "you".这种直接拼接的情况下,String速度最高.这是因为jvm的优化问题,jvm会自动识别,把&quo

2017.11.11 B201 练习题思路及解题方法

2017.11.11 B201 练习题思路及解题方法 题目类型及涵盖知识点 本次总共有6道题目,都属于MISC分类的题目,涵盖的知识点有 信息隐藏 暴力破解 音轨,摩斯电码 gif修改,base64原理 序列密码 各题的解题思路及过程 签到题:隐写诶.jpeg[知识点:信息隐藏] 本题为 隐写诶.jpeg 的图片文件,可以对该文件尝试一些基本的图片隐写解题思路,如将文件后缀名由 .jpeg 更改为 .txt 后利用记事本打开,或直接对文件点击右键后 打开方式→记事本打开,在打开的记事本窗口中获得

[LOJ 6249]「CodePlus 2017 11 月赛」汀博尔

Description 有 n 棵树,初始时每棵树的高度为 H_i,第 i 棵树每月都会长高 A_i.现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于 L,而且木料必须是整棵树(即不能为树的一部分).现在问你最少需要等多少个月才能满足订单. Input 第一行 3 个用空格隔开的非负整数 n,S,L,表示树的数量.订单总量和单块木料长度限制.第二行 n 个用空格隔开的非负整数,依次为 H1,H2,…,Hn.第三行 n 个用空格隔开的非负整数,依次为 A1,A2,…,An. Ou