题目大意:
给你一个$n(n\le10^5)$个点,$m(m\le2\times10^5)$条边的无向图,每个点有一个颜色$c_i$,每条边有一个边权$w_i$。$q(q\le2\times10^5)$组询问$(x,w)$,每次询问从点$x$出发,只经过边权不超过$w$的边所能到达的连通块中,出现次数最多的颜色中,编号最小的颜色是多少?
思路:
Kruskal重构树+线段树合并。时间复杂度$O(m\log m+q\log n)$。
1 #include<cstdio> 2 #include<cctype> 3 #include<climits> 4 #include<cstring> 5 #include<algorithm> 6 inline int getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^‘0‘; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^‘0‘); 11 return x; 12 } 13 const int N=2e5,logN=18,M=2e5; 14 int n,m,tot,ch[N][2],val[N]={INT_MAX},ans[N]; 15 struct Edge { 16 int u,v,w; 17 bool operator < (const Edge &another) const { 18 return w<another.w; 19 } 20 }; 21 Edge e[M]; 22 struct DisjointSet { 23 int anc[N]; 24 void reset() { 25 for(register int i=0;i<N;i++) anc[i]=i; 26 } 27 int find(const int &x) { 28 return x==anc[x]?x:anc[x]=find(anc[x]); 29 } 30 void merge(const int &x,const int &y) { 31 anc[find(x)]=find(y); 32 } 33 bool same(const int &x,const int &y) { 34 return find(x)==find(y); 35 } 36 }; 37 DisjointSet s; 38 inline void kruskal() { 39 tot=n; 40 s.reset(); 41 std::sort(&e[0],&e[m]); 42 for(register int i=0;i<m;i++) { 43 const int &u=e[i].u,&v=e[i].v,&w=e[i].w; 44 if(!s.same(u,v)) { 45 val[++tot]=w; 46 ch[tot][0]=s.find(u); 47 ch[tot][1]=s.find(v); 48 s.merge(u,tot); 49 s.merge(v,tot); 50 } 51 } 52 } 53 class SegmentTree { 54 private: 55 struct Node { 56 int max,val,left,right; 57 }; 58 Node node[N/2*logN]; 59 int new_node(const int &p) { 60 node[++root[0]]=node[p]; 61 return root[0]; 62 } 63 void push_up(const int &p) { 64 if(node[node[p].left].max>=node[node[p].right].max) { 65 node[p].max=node[node[p].left].max; 66 node[p].val=node[node[p].left].val; 67 } else { 68 node[p].max=node[node[p].right].max; 69 node[p].val=node[node[p].right].val; 70 } 71 } 72 public: 73 int root[N]; 74 void reset() { 75 memset(root,0,sizeof root); 76 } 77 void modify(int &p,const int &b,const int &e,const int &x) { 78 p=new_node(p); 79 if(b==e) { 80 node[p]=(Node){1,x,0,0}; 81 return; 82 } 83 const int mid=(b+e)>>1; 84 if(x<=mid) modify(node[p].left,b,mid,x); 85 if(x>mid) modify(node[p].right,mid+1,e,x); 86 push_up(p); 87 } 88 int merge(const int &p,const int &q,const int &b,const int &e) { 89 if(!p||!q) return p|q; 90 if(b==e) { 91 node[p].max+=node[q].max; 92 return p; 93 } 94 const int mid=(b+e)>>1; 95 node[p].left=merge(node[p].left,node[q].left,b,mid); 96 node[p].right=merge(node[p].right,node[q].right,mid+1,e); 97 push_up(p); 98 return p; 99 } 100 int query(const int &p) const { 101 return node[p].val; 102 } 103 }; 104 SegmentTree t; 105 int dep[N],anc[N][logN]; 106 inline int log2(const float &x) { 107 return ((unsigned&)x>>23&255)-127; 108 } 109 void dfs(const int &x,const int &par) { 110 dep[x]=dep[anc[x][0]=par]+1; 111 for(register int i=1;i<=log2(dep[x]);i++) { 112 anc[x][i]=anc[anc[x][i-1]][i-1]; 113 } 114 if(x<=n) return; 115 dfs(ch[x][0],x); 116 dfs(ch[x][1],x); 117 t.root[x]=t.merge(t.root[ch[x][0]],t.root[ch[x][1]],1,n); 118 ans[x]=t.query(t.root[x]); 119 } 120 inline int find(int x,const int &w) { 121 for(register int i=log2(dep[x]);~i;i--) { 122 if(val[anc[x][i]]<=w) x=anc[x][i]; 123 } 124 return x; 125 } 126 int main() { 127 const int T=getint(); 128 for(register int i=1;i<=T;i++) { 129 t.reset(); 130 n=getint(),m=getint(); 131 for(register int i=1;i<=n;i++) { 132 t.modify(t.root[i],1,n,ans[i]=val[i]=getint()); 133 } 134 for(register int i=0;i<m;i++) { 135 const int u=getint(),v=getint(),w=getint(); 136 e[i]=(Edge){u,v,w}; 137 } 138 kruskal(); 139 dfs(tot,0); 140 printf("Case #%d:\n",i); 141 for(register int q=getint(),last=0;q;q--) { 142 const int x=getint()^last,w=getint()^last; 143 printf("%d\n",last=ans[find(x,w)]); 144 } 145 } 146 return 0; 147 }