做这个题做的我心态爆炸,昨天打第一场牛客网暑期ACM多校训练赛之前就在做这个题,一直tle,不知道为什么。。。搞的我打比赛的状态都不好了(掩盖一下我菜的事实)
今天准备再进行优化一下,看能不能过
把用vector存图改成数组式
加输入输出优化
然而还是tle,不可能啊,网上博客不也是这样吗,只不过LCA是不是离线和在线的问题,但不至于在线就tle吧,我又对比了其他博客的代码,思想差不多,应该没有问题,结果。。。。。
突然看到我的分块大小是pow(n,0.45)。。。难道是这个原因,昨天把sqrt(n)改成pow(n,0.45),想着会不会侥幸就过了,结果就忘记换回来了,所以换回sqrt(n)再交一发,就。。。。。。。过了
我的丑陋代码:
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=200000+100;
int deep[maxn],fa[maxn][20];
int unit,block,R[maxn];
int st[maxn],top;
int u,v;
struct Edge{
int from,to;
int next;
}edge[maxn*2];
int head[maxn],tot;
bool vis[maxn];
int ans[maxn];
int Ans[maxn];
int n,m;
void dfs(int u){
for(int i=1;;i++){
if((1<<i)>deep[u]) break;
fa[u][i]=fa[fa[u][i-1]][i-1];
}
int bottom=top;
for(int i=head[u];i!=-1;i=edge[i].next){
Edge e=edge[i];
int v=e.to;
if(fa[v][0]) continue;
deep[v]=deep[u]+1;
fa[v][0]=u;
dfs(v);
if(top-bottom>=unit){
block++;
while(top!=bottom) R[st[top--]]=block;
}
}
st[++top]=u;
}
inline int LCA(int x,int y){
if(deep[x]<deep[y]) swap(x,y);
int dis=deep[x]-deep[y];
for(int i=0;;i++){
if((1<<i)>dis) break;
if((1<<i)&dis) x=fa[x][i];
}
if(x==y) return x;
for(int i=20;i>=0;i--){
if((1<<i)>deep[x]) continue;
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
}
return fa[x][0];
}
struct Moq{
int u,v;
int id;
}moq[maxn];
inline bool cmp(Moq a,Moq b){
return R[a.u]==R[b.u]?R[a.v]<R[b.v]:R[a.u]<R[b.u];
}
struct DataBlock{
struct OneBlock{
int l,r;
}oneblock[500];
int unit,block_num,n,num[maxn],R[maxn],sum[500];
void init(){
unit=sqrt(n);
block_num=n/unit+(n%unit!=0);
for(int i=1;i<=n;i++) R[i]=(i-1)/unit+1,num[i]=0;
for(int i=1;i<=block_num;i++) oneblock[i].l=(i-1)*unit+1,oneblock[i].r=i*unit,sum[i]=0;
oneblock[block_num].r=n;
}
inline void Add(int ind,int v){
num[ind]+=v;
if(num[ind]%2) sum[R[ind]]++;
else sum[R[ind]]--;
}
inline int getMin(){
for(int i=1;i<=block_num;i++){
if(sum[i]!=(oneblock[i].r-oneblock[i].l+1)){
for(int j=oneblock[i].l;j<=oneblock[i].r;j++){
if(num[j]%2==0) return j;
}
}
}
}
}Data;
inline Run(int ind){
if(vis[ind]){
Data.Add(ans[ind],-1);
vis[ind]=0;
}
else{
Data.Add(ans[ind],1);
vis[ind]=1;
}
}
inline move(int x,int y){
if(deep[x]<deep[y]) swap(x,y);
while(deep[x]>deep[y]) Run(x),x=fa[x][0];
while(x!=y) Run(x),Run(y),x=fa[x][0],y=fa[y][0];
}
void Mo(){
for(int i=1;i<=m;i++){
while(u!=moq[i].u) move(u,moq[i].u),u=moq[i].u;
while(v!=moq[i].v) move(v,moq[i].v),v=moq[i].v;
int lca=LCA(u,v);
Run(lca);
Ans[moq[i].id]=Data.getMin();
Run(lca);
}
}
void init(){
u=v=1;
block=top=tot=0;
deep[1]=0;
for(int i=1;i<=n;i++) fa[i][0]=0,vis[i]=false,head[i]=-1;
fa[1][0]=-1;
}
inline void scan_d(int &res){
res=0;
char ch;
ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') res=res*10+(ch-'0'),ch=getchar();
}
inline void print_d(int res){
if(res>9) print_d(res/10);
putchar(res%10+'0');
}
int main(){
int T;
scan_d(T);
while(T--){
scan_d(n);
scan_d(m);
init();
int Max=0;
for(int i=1;i<=n;i++) scan_d(ans[i]),Max=max(Max,ans[i]);
for(int i=1;i<n;i++){
int a,b;
scan_d(a);
scan_d(b);
edge[tot].from=a;
edge[tot].to=b;
edge[tot].next=head[a];
head[a]=tot++;
edge[tot].from=b;
edge[tot].to=a;
edge[tot].next=head[b];
head[b]=tot++;
}
unit=sqrt(n);
dfs(1);
while(top) R[st[top--]]=block;
Data.n=Max+1;
Data.init();
for(int i=1;i<=m;i++){
scan_d(moq[i].u);
scan_d(moq[i].v);
moq[i].id=i;
}
sort(moq+1,moq+m+1,cmp);
Mo();
for(int i=1;i<=m;i++) print_d(Ans[i]),putchar('\n');
}
}