250616 模拟赛

分数:\(10+25+0=35\)

一上来看完题感觉 T1 直接秒了 \(n^2\) 正解也不远了,然后看看后面的题发现 T2 会暴力,T3 没啥思路。

然后写了半天调了半天拍了半天感觉 T1 贪心假了。然后交了爆搜十分。然后写了一下 T2 暴力。


T1 火山

什么什么 Hall 定理,我不会。


T2 共情

给你 \(n\) 条线段,端点为 \((0,a_i),(W,b_i)\),在坐标系上从左到右画出来这条线段,中途遇到其他线段就停止,如果 \(c_i=1\),就在坐标系上留下这条线段。求每条线段停止的坐标。

暴力是简单的,每次枚举已经有的所有线段然后看哪一条和当前直线有交点而且是第一个遇到的,时间复杂度大概是 \(O(n^2)\)

考虑优化。发现将每条线遇到的第一条线记作它的父亲可以建成一棵树,那么每次找 \(a_i\) 的前驱和后继对应的叶子,在它们之间的路径上可以找到和当前直线相交的线段,树上倍增一下就好了。

问题是如何倍增,发现找当前线段和当前树上节点的交点额然后发现在相交线段以上的交点的位置不在线段上。然后就可以倍增去找了。

点击查看代码
#include<bits/stdc++.h>
#define _ __int128
#define ll long long
#define pff pair<fr,fr>
#define f first
#define s second
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(_ x)
{
	if(x>9)write(x/10);putchar(x%10+'0');
}
const int N=3e5+10;
struct fr{
	_ a,b;
	void print()
	{
		write(a);putchar('/');write(b);
	}
	void re()
	{
		if(!a&&!b)return;
		_ g=__gcd(a,b);a/=g;b/=g;
	}
	friend bool operator>(fr a,fr b)
	{
		return a.a*b.b>a.b*b.a;
	}
	friend fr operator+(fr x,fr y)
	{
		fr c={x.a*y.b+y.a*x.b,x.b*y.b};
		if(c.b<0)c.a=-c.a,c.b=-c.b;c.re();return c;
	}
	friend fr operator-(fr x,fr y)
	{
		y.a=-y.a;return x+y;
	}
	friend fr operator*(fr x,fr y)
	{
		fr c={x.a*y.a,x.b*y.b};
		if(c.b<0)c.a=-c.a,c.b=-c.b;c.re();return c;
	}
	friend fr operator/(fr x,fr y)
	{
		return x*(fr){y.b,y.a};
	}
};
pff s[N];
int lmt;
void print(pff x)
{
	putchar('(');x.f.print();putchar(',');x.s.print();putchar(')');
}
int n,w;
int a[N],b[N],c;
fr k[N];
pff fl={{20000000000000000,1},{20000000000000000,1}};
pff sol(fr k1,fr b1,fr k2,fr b2)
{
	fr k=k1-k2,b=b2-b1;
	fr x=b/k,y=(x*k1)+b1;return {x,y};
}
pff cro(int i,int j)
{
	if(i>j)swap(i,j);
	if(!i)return {{w,1},{b[j],1}};
	if((_)(a[i]-a[j])*(b[i]-b[j])>0)return fl;
	return sol(k[i],{a[i],1},k[j],{a[j],1});
}
bool chk(int x,int i)
{
	return cro(i,x).f>s[x].f;
}
int f[N][50],d[N];
int lca(int x,int y)
{
	if(x==y)return x;
	if(d[x]<d[y])swap(x,y);
	for(int i=lmt;~i;i--)if(d[f[x][i]]>=d[y])x=f[x][i];
	if(x==y)return x;
	for(int i=lmt;~i;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}
int tot=0;
int que(int x,int fa,int i)
{
	for(int j=lmt;~j;j--)
	{
		if(f[x][j]&&d[f[x][j]]>d[fa]&&chk(f[x][j],i))x=f[x][j];
	}
	if(x&&!chk(x,i))return x;
	x=f[x][0];
	if(x&&d[x]>d[fa]&&!chk(x,i))return x;
	return 0;
}
map<int,int>mp;
map<int,int>::iterator it;
int x,y,v,i;
signed main()
{
	freopen("empathy.in","r",stdin);
	freopen("empathy.out","w",stdout);

	n=read();w=read();mp[0]=0;mp[1e9+1]=0;lmt=log2((uint)n)+1;i=1;d[0]=1;
	while(n--)
	{
		a[i]=read();b[i]=read();c=read();
		int ans=0,v=0;
		k[i]={b[i]-a[i],w};k[i].re();int fa=0;
		s[i]={{w,1},{b[i],1}};
		it=mp.lower_bound(a[i]);x=it->s;--it;y=it->s;v=lca(x,y);
		ans=que(y,v,i);
		pff t=cro(ans,i);
		if(s[i].f>t.f)s[i]=t,fa=ans;
		ans=que(x,v,i);
		t=cro(ans,i);
		if(s[i].f>t.f)s[i]=t,fa=ans;
		if(v&&!chk(v,i))
		{
			ans=v;t=cro(ans,i);
			if(s[i].f>t.f)s[i]=t,fa=ans;
		}
		print(s[i]);puts("");
		if(c)
		{
			f[i][0]=fa;d[i]=d[fa]+1;
			for(int j=1;j<=lmt;j++)f[i][j]=f[f[i][j-1]][j-1];
			mp[a[i]]=i;i++;
		}
	}
	return 0;
} 

T3 仇恨

posted @ 2025-06-26 20:32  baiguifan  阅读(11)  评论(0)    收藏  举报