Oct 12

这一次纯纯的什么想法都没有,只好打了一大堆暴力。

T1

loj 5459

这个很神秘了......

我们维护一个点最右边 a 不同和 b 不同,\(O(n)\) 不难去做,记录为 \(nxta[i],nxtb[i]\)

对于每个询问,进行如下的判断。

  1. 是否存在,也就是左端点的 \(nxta[l]\)\(nxtb[l]\) 是不是小于等于 \(r\)

  2. 检查 \(nxta[l]\)\(l\) 的 b 是不是不同的,合理就取。

  3. 检查 \(nxtb[l]\)\(l\) 的 a 是不是不同的,合理就取。

  4. 剩下的情况就是直接使用 nxta[l] 和 nxtb[l] 就行了。

非常巧妙的思想。

代码↓

点击查看代码
//this is a tang problem
//Why i did not came up with that?
#include <bits/stdc++.h>
#define getchar getchar_unlocked
using namespace std;
const int MN=1e6+116;
int n, k, a[MN], b[MN], nxta[MN], nxtb[MN];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
void write(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return;
}
void Read(){
	n=read(); for(int i=1; i<=n; ++i) a[i]=read(), b[i]=read();
	int posa=1;
	for(int i=1; i<=n; ++i){
		posa=max(posa,i);
		while(a[posa]==a[i]&&posa<=n) ++posa;
		nxta[i]=posa;
	}
	int posb=1;
	for(int i=1; i<=n; ++i){
		posb=max(posb,i);
		while(b[posb]==b[i]&&posb<=n) ++posb;
		nxtb[i]=posb;
	}
}
int main(){
	Read(); k=read();
	while(k--){
		int l, r; l=read(); r=read();
		if(nxta[l]>r||nxtb[l]>r){
			write(0); putchar(' '); write(0); putchar('\n');
		}else if(b[nxta[l]]!=b[l]){
			write(l); putchar(' '); write(nxta[l]); putchar('\n');
		}else if(a[nxtb[l]]!=a[l]){
			write(l); putchar(' '); write(nxtb[l]); putchar('\n');
		}else{
			write(nxta[l]); putchar(' '); write(nxtb[l]); putchar('\n');
		}
	}
	return 0;
}

T2

P4616

神秘题。

发现可以转化成一个数连倍数,其它边都是不必要的。

建成一棵树。

求中途边权最大,倍增可做。

代码↓

点击查看代码
//This is a very good T2
//i kinda like it
//however i only have 60pts
#include <bits/stdc++.h>
using namespace std;
const int MN=3e5+116;
struct Node{
	int nxt, to, w;
}node[MN];
int head[MN], tottt;
void insert(int u, int v, int w){
	node[++tottt].to=v;
	node[tottt].w=w;
	node[tottt].nxt=head[u];
	head[u]=tottt; return;
}
int jump[MN][26], father[MN];
int tmp[MN][26], n, m, q;
int find(int x){
	if(father[x]!=x) father[x]=find(father[x]);
	return father[x];
}
void merge(int x, int y){
	x=find(x), y=find(y);
	if(x==y) return;
	father[x]=y; return;
}
int depth[MN], lg[MN];
void dfs(int u, int father, int w){
	jump[u][0]=father; tmp[u][0]=w;
	depth[u]=depth[father]+1;
	for(int i=1; i<=25; ++i){
		jump[u][i]=jump[jump[u][i-1]][i-1];
		tmp[u][i]=max(tmp[u][i-1],tmp[jump[u][i-1]][i-1]);
	}
	for(int i=head[u];i;i=node[i].nxt){
		int v=node[i].to;
		if(v==father) continue;
		dfs(v,u,node[i].w);
	}
}
int Lca(int x, int y){
	int res=0;
	if(depth[x]<depth[y]) swap(x,y);
	while(depth[x]!=depth[y]){
		res=max(res,tmp[x][lg[depth[x]-depth[y]]]);
		x=jump[x][lg[depth[x]-depth[y]]];
	}
	if(x==y) return res;
	for(int i=25; i>=0; --i){
		if(jump[x][i]!=jump[y][i]){
			res=max(res,max(tmp[x][i],tmp[y][i]));
			x=jump[x][i], y=jump[y][i];
		}
	}
	return max(res,max(tmp[x][0],tmp[y][0]));
}
void solve(){
	cin>>n>>m>>q; lg[0]=-1;
	for(int i=1; i<MN; ++i) lg[i]=lg[i>>1]+1;
	for(int i=0; i<MN; ++i) father[i]=i;
	memset(tmp,0x3f,sizeof(tmp));
	for(int i=m; i>=1; --i){
		for(int j=i*2,u,v; j<=n; j+=i){
			u=find(i), v=find(j);
			if(u==v) continue;
			merge(u,v);
			insert(i,j,m-i+1);
			insert(j,i,m-i+1);
		}
	}
	dfs(1,0,0);
	for(int i=1; i<=q; ++i){
		int u, v; cin>>u>>v;
		cout<<Lca(u,v)<<'\n';
	}
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	solve();
	return 0;
}
posted @ 2025-10-12 17:12  BaiBaiShaFeng  阅读(3)  评论(0)    收藏  举报
Sakana Widget右下角定位