250627 模拟赛

分数:\(100+15+60=175\)

首次在 noi 模拟赛中使用正解通过了非原题的 T1.

先看 T1,看完感觉比较可做但是往后去看了,然后先写了 2.5 h T3 60 分。可能是因为太久没写了,好像忘记树剖。然后还有一些奇怪的错误。最后五分钟剩五分调不出来了,哎哎不对好像是三十分。


T1 第五人格

非常的简单,发现这个范围可以枚举最晚出成绩的一天,然后如果枚举这个就可以贪心地去求最少花费。

首先对于一个日期 \(C\) 的贡献是固定的,然后就是 \(A\)\(B\)。分情况讨论,如果 \(B\le A\) 显然是优先用 \(B\) ;否则先用最多的 \(A\),然后再用 \(B\)。这样暴力求一次是 \(O(n)\) 的,排序加前缀和优化可以做到 \(O(1)\)

当然还可以发现这个花费关于日期的函数应该是凹的,所以可以三分。然后就做完了,最优复杂度是 \(O(n+\log n)\)

点击查看代码
#include<bits/stdc++.h>
#define int ll
#define ll __int128
using namespace std;
inline ll read()
{
	ll t=0;char h=getchar();
	while(!isdigit(h))h=getchar();
	while(isdigit(h))t=(t<<1)+(t<<3)+(h^48),h=getchar();
	return t;
}
void write(ll x)
{
	if(x>9)write(x/10);putchar(x%10+'0');
}
const int N=1e5+10;
ll ans=0x3f3f3f3f3f3f3f3f;
ll A,B,C;
int n,m;
int t[N],b[N];
int now=0;
ll calc(int x)
{
	ll res=0;int num1=0,num2=0;
	for(int i=1;i<=n;i++)if(t[i]<x)res+=C*(x-t[i]);
	for(int i=1;i<=m;i++)if(b[i]>x)num1+=b[i]-x;else num2+=x-b[i];
	if(B<=A)res+=B*num1;
	else
	{
		if(num2>=num1)res+=num1*A;
		else res+=num2*A+(num1-num2)*B;
	}
	return res;
}
signed main()
{
	A=read(),B=read(),C=read();
	n=read();m=read();
	for(int i=1;i<=n;i++)t[i]=read();
	for(int i=1;i<=m;i++)b[i]=read(),now=max(now,b[i]);
	sort(t+1,t+n+1);sort(b+1,b+m+1);
	int l=1,r=now;
	while(l+100<r)
	{
		int m1=l+(r-l)/3,m2=r-(r-l)/3;
		if(calc(m1)<calc(m2))r=m2;
		else l=m1;
	}
	for(int i=l;i<=r;i++)ans=min(ans,calc(i));
	write(ans);
	return 0;
}

T2 星穹铁道


T3 王者荣耀

神经病题我都想到动态维护当前所有经过的路径但是没想到可以树上差分

点击查看代码
#include<bits/stdc++.h>
#define swap(x,y) (x^=y^=x^=y)
#define mid ((lf+rt)>>1)
#define ll long long
using namespace std;
inline int read()
{
	int t=0;char h=getchar();
	while(!isdigit(h))h=getchar();
	while(isdigit(h))t=(t<<1)+(t<<3)+(h^48),h=getchar();
	return t;
}
void write(ll x)
{
	if(x>9)write(x/10);putchar(x%10+'0');
}
const int N=1e5+10;
int lk[N],nxt[N<<1],to[N<<1],len=1;
inline void insert(int x,int y)
{
	to[++len]=y;nxt[len]=lk[x];lk[x]=len;
}
int n,m,x,y;
int f0[N],d[N],bs[N],siz[N],tt=0,st[N<<1][30],pos[N];
void dfs1(int x)
{
	st[++tt][0]=x;pos[x]=tt;siz[x]=1;d[x]=d[f0[x]]+1;
	for(int i=lk[x],y;i;i=nxt[i])
	{
		if(d[y=to[i]])continue;
		f0[y]=x,dfs1(y),siz[x]+=siz[y];
		(siz[y]>siz[bs[x]])&&(bs[x]=y);
		st[++tt][0]=x;
	}
}
int tp[N],dfn[N],now=0;
void dfs2(int x,int top)
{
	tp[x]=top;dfn[x]=++now;
	if(bs[x])dfs2(bs[x],top);
	for(int i=lk[x],y;i;i=nxt[i])if(!dfn[y=to[i]])dfs2(y,y);
}
int cnt[N*200],sum[N*200],lc[N*200],rc[N*200],tot=0;
int rt[N];
inline void psu(int p,int lf,int rt)
{
	sum[p]=(cnt[p]>0)?rt-lf+1:sum[lc[p]]+sum[rc[p]];
}
void upd(int l,int r,int k,int&p,int lf,int rt)
{
	if(!p)p=++tot;
	if(l<=lf&&rt<=r)
	{
		cnt[p]+=k;psu(p,lf,rt);return;
	}
	if(l<=mid)upd(l,r,k,lc[p],lf,mid);
	if(r>mid)upd(l,r,k,rc[p],mid+1,rt);
	psu(p,lf,rt);
}
void upd_path(int x,int y,int k,int&root)
{
	while(tp[x]!=tp[y])
	{
		(d[tp[x]]<d[tp[y]])&&swap(x,y);
		upd(dfn[tp[x]],dfn[x],k,root,1,n);
		x=f0[tp[x]];
	}
	(d[x]<d[y])&&swap(x,y);
	upd(dfn[y],dfn[x],k,root,1,n);
}
bool f;
void merge(int&p,int q,int lf,int rt)
{
	if(!p||!q)
	{
		p=p+q;return;
	}
	cnt[p]+=cnt[q];
	merge(lc[p],lc[q],lf,mid);
	merge(rc[p],rc[q],mid+1,rt);
	psu(p,lf,rt);
}
ll ans=0;
void dfs3(int x)
{
	for(int i=lk[x],y;i;i=nxt[i])if((y=to[i])!=f0[x])dfs3(y),merge(rt[x],rt[y],1,n);
	(sum[rt[x]])&&(ans+=sum[rt[x]]-1);
}
int lg[N<<1];
inline int lca(int x,int y)
{
	x=pos[x];y=pos[y];(x>y)&&swap(x,y);int k=lg[y-x+1];
	return(d[st[x][k]]<d[st[y-(1<<k)+1][k]])?st[x][k]:st[y-(1<<k)+1][k];
}
int main()
{
	n=read();m=read();
	for(int i=2;i<=n*2;i++)lg[i]=lg[i>>1]+1;
	for(int i=1;i<n;i++)x=read(),y=read(),insert(x,y),insert(y,x);
	dfs1(1);dfs2(1,1);
	for(int j=1,lmt=lg[tt]+1;j<=lmt;j++)
		for(int i=1;i+(1<<j)<=tt+1;i++)
			st[i][j]=(d[st[i][j-1]]<d[st[i+(1<<(j-1))][j-1]])?st[i][j-1]:st[i+(1<<(j-1))][j-1];
	for(int i=1;i<=m;i++)
	{
		x=read();y=read();int l=lca(x,y);
		upd_path(x,y,1,rt[x]);upd_path(x,y,1,rt[y]);
		upd_path(x,y,-1,rt[l]);if(f0[l])upd_path(x,y,-1,rt[f0[l]]);
	}
	dfs3(1);
	write(ans/2);
	return 0;
}
posted @ 2025-06-29 17:14  baiguifan  阅读(16)  评论(0)    收藏  举报