B
C
pro:
给出一个凸多边形
和它的一个三角剖分
在这种无向图上查询q次最短路
sol:
分治+bfs
每次选择一条边(a,b)进行分治
对于跨越这条边的询问(x,y)
一定会经过a,b中的一个
分别以a,b为起点计算最短路
然后分治块内部查询递归下去即可
写法的话考虑每次对所有节点重新标号进行分治
F
pro:
在一面长度为n的墙的基础上加石头
第i个位置可以加石头当且仅当当前i-1和i+1的高度都>=i的高度
询问加<=m块石头最多可以是这面墙的最高点多高
sol:
考虑枚举最高点
然后计算该点高度是否可以达到k
这个可以二分
然后发现想让i达到k
i-1和i+1就要k-1
i-2和i+2就要k-2
......
左边需要找到一个最大的j满足(k-(i-j)<=aj)
化简后为(k-i<=aj-j)
右边需要找到一个最小的j满足(k-(j-i)<=aj)
化简后为(k+i<=aj+j)
也就是变成了一个区间lower_bound问题
这个问题显然可以一个log解决
我这里用了线段树区间二分的方法
二分+rmq也可以
然后这样做的总复杂度就是(O(nlog^2n))
似乎有一个log的做法,由于博主Creed_太菜了,并不是很会
K
pro:从0开始依次画n条线,每次从(X_{i-1})画到(X_i)
现在要求改变一些(X_i),((X_i)始终>0)使得这些线不存在相交的情况
问最多有多少个不改变
画一张(X_i)为纵坐标,i为横坐标的路径折线图
发现只能保留一个单增子序列和一个单减子序列
而且还不能相交
那就先dp出来然后
排个序扫一下就行了
#include<bits/stdc++.h>
#define N 550000
#define eps 1e-7
#define inf 1e9+7
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
inline int read()
{
char ch=0;
int x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
return x*flag;
}
struct Segment_Tree
{
#define lson o<<1
#define rson o<<1|1
#define mid ((l+r)>>1)
int f[N*4],g[N*4];
inline void pushup(int o)
{
f[o]=max(f[lson],f[rson]);
g[o]=max(g[lson],g[rson]);
}
void optset(int o,int l,int r,int q,int x,int y)
{
if(l==r){f[o]=x;g[o]=y;return;}
if(q<=mid)optset(lson,l,mid,q,x,y);
if(q>mid)optset(rson,mid+1,r,q,x,y);
pushup(o);
}
int queryf(int o,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return f[o];
int ans=0;
if(ql<=mid)ans=max(ans,queryf(lson,l,mid,ql,qr));
if(qr>mid)ans=max(ans,queryf(rson,mid+1,r,ql,qr));
return ans;
}
int queryg(int o,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return g[o];
int ans=0;
if(ql<=mid)ans=max(ans,queryg(lson,l,mid,ql,qr));
if(qr>mid)ans=max(ans,queryg(rson,mid+1,r,ql,qr));
return ans;
}
}T;
struct node{int x,a,b;}p[N];
bool cmp(node a,node b){return a.x<b.x;}
int h[N];
int main()
{
int n=read(),ans=0;
for(int i=1;i<=n;i++)h[i]=read();
for(int i=1;i<=n;i++)
{
p[i].x=h[i];
p[i].a=T.queryf(1,1,n,h[i],n)+1;
p[i].b=T.queryg(1,1,n,1,h[i])+1;
T.optset(1,1,n,h[i],p[i].a,p[i].b);
}
sort(p+1,p+n+1,cmp);
for(int i=1,k=0;i<=n;i++)ans=max(ans,p[i].a+k),k=max(k,p[i].b);
printf("%d",ans);
return 0;
}