多校省选模拟4


T1 图论题

从 s 和 t 分别跑个最短路,然后建出到 s 的凸包,用 t 二分去就行了

从 s 跑 k 次同时维护李超树可以求出连 k 条边的最优解

T2 构造题

没想懂细节

T3 数据结构题

因为是顺序改题,就没有然后了,,,

代码

T1

#include
using namespace std;
#define il inline
#define int long long
const int N=200011;
const int inf=1e18;
struct bag_{int x,y;friend bool operator<(bag_ a,bag_ b){return a.x!=b.x?a.xb.y;}}now;
struct e_{int v,w;friend bool operator<(e_ a,e_ b){return a.w>b.w;}};
bool jud[N];
int n,m,s,t;
int d[2][N];
vector v[2][N];
vector bag;
priority_queue dui;
il int min_(int x,int y){return x>y?y:x;}
il double get_xl(bag_ a,bag_ b){return (b.y-a.y)/(b.x-a.x);}
il bool jd(bag_ a,bag_ b,bag_ c){return (b.x==c.x)||get_xl(a,c)>=get_xl(b,c);}
il int get_ans(bag_ a,int x){return x*x+a.y-2*a.x*x;}
il int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
void dij(int x,bool jd)
{
	memset(d[jd],0x3f,sizeof(d[jd]));
	memset(jud,0,sizeof(jud));
	d[jd][x]=0;
	dui.push({x,0});
	e_ u;
	while(dui.size())
	{
		u=dui.top(),dui.pop();
		if(jud[u.v]) continue;
		jud[u.v]=1;
		for(e_ y : v[jd][u.v])
			if(d[jd][y.v]>d[jd][u.v]+y.w)
			{
				d[jd][y.v]=d[jd][u.v]+y.w;
				dui.push({y.v,d[jd][y.v]});
			}
	}
	return;
}
int two(int x)
{
	int sz=bag.size();
	if(sz==0) return inf;
	if(sz==1) return get_ans(bag[0],x);
	if(sz==2) return min_(get_ans(bag[0],x),get_ans(bag[1],x));
	if(get_ans(bag[0],x)>1;
		ansl=get_ans(bag[mid],x);
		ansr=get_ans(bag[mid+1],x);
		if(ansl1&&jd(bag[sz-2],bag[sz-1],now)) --sz,bag.pop_back();
		bag.push_back(now),++sz;
	}
	int ans=inf;
	for(int i=1;i<=n;++i) ans=min_(ans,d[0][i]+two(i));
	cout<