Oct 12
这一次纯纯的什么想法都没有,只好打了一大堆暴力。
T1
loj 5459
这个很神秘了......
我们维护一个点最右边 a 不同和 b 不同,\(O(n)\) 不难去做,记录为 \(nxta[i],nxtb[i]\)。
对于每个询问,进行如下的判断。
-
是否存在,也就是左端点的 \(nxta[l]\) 和 \(nxtb[l]\) 是不是小于等于 \(r\)。
-
检查 \(nxta[l]\) 和 \(l\) 的 b 是不是不同的,合理就取。
-
检查 \(nxtb[l]\) 和 \(l\) 的 a 是不是不同的,合理就取。
-
剩下的情况就是直接使用 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;
}

浙公网安备 33010602011771号