1.一棵树,边权为1,每次给两个点a,b,d1,d2,找到任意一个到a距离为d1,到b距离为d2的点。
大力分类讨论即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1E6+5; 4 int n,q; 5 int TI,dfn[maxn],low[maxn],back[maxn],maxd[maxn]; 6 int minn[maxn*4],maxx[maxn*4]; 7 int ans[maxn]; 8 inline int read() 9 { 10 char ch=getchar(); 11 while(!isdigit(ch))ch=getchar(); 12 int s=ch-'0';ch=getchar(); 13 while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} 14 return s; 15 } 16 int G[55]; 17 inline void write(int x) 18 { 19 if(x<0)putchar('-'),x=-x; 20 int g=0; 21 do{G[++g]=x%10;x/=10;}while(x); 22 for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n'); 23 } 24 int size,head[maxn]; 25 int dep[maxn],fa[maxn][21]; 26 struct edge 27 { 28 int to,next; 29 }E[maxn*2]; 30 inline void add(int u,int v) 31 { 32 E[++size].to=v; 33 E[size].next=head[u]; 34 head[u]=size; 35 } 36 void dfs(int u,int F,int d) 37 { 38 low[u]=dfn[u]=++TI; 39 back[TI]=u; 40 dep[u]=d; 41 fa[u][0]=F; 42 for(int i=1;i<21;++i) 43 fa[u][i]=fa[fa[u][i-1]][i-1]; 44 for(int i=head[u];i;i=E[i].next) 45 { 46 int v=E[i].to; 47 if(v==F) 48 continue; 49 dfs(v,u,d+1); 50 low[u]=low[v]; 51 maxd[u]=max(maxd[u],maxd[v]+1); 52 } 53 } 54 inline int lca(int x,int y) 55 { 56 if(dep[x]<dep[y]) 57 swap(x,y); 58 int d=dep[x]-dep[y]; 59 for(int i=0;i<21;++i) 60 if(d&(1<<i)) 61 x=fa[x][i]; 62 if(x==y) 63 return x; 64 for(int i=20;i>=0;--i) 65 if(fa[x][i]!=fa[y][i]) 66 x=fa[x][i],y=fa[y][i]; 67 return fa[x][0]; 68 } 69 inline int jump(int x,int d) 70 { 71 for(int i=0;i<21;++i) 72 if(d&(1<<i)) 73 x=fa[x][i]; 74 return x; 75 } 76 inline int dis(int x,int y) 77 { 78 return dep[x]+dep[y]-2*dep[lca(x,y)]; 79 } 80 void build(int l,int r,int num) 81 { 82 if(l==r) 83 { 84 minn[num]=maxx[num]=dep[back[l]]; 85 return; 86 } 87 int mid=(l+r)>>1; 88 build(l,mid,num<<1),build(mid+1,r,num<<1|1); 89 minn[num]=min(minn[num<<1],minn[num<<1|1]); 90 maxx[num]=max(maxx[num<<1],maxx[num<<1|1]); 91 } 92 void ask(int L,int R,int l,int r,int x,int num,int&ans) 93 { 94 if(r<L||R<l||L>R) 95 return; 96 if(ans!=-1) 97 return; 98 int mid=(l+r)>>1; 99 if(x<minn[num]||maxx[num]<x) 100 return; 101 if(L<=l&&r<=R) 102 { 103 if(l==r) 104 { 105 ans=back[l]; 106 return; 107 } 108 if(minn[num<<1]<=x&&x<=maxx[num<<1]) 109 ask(L,R,l,mid,x,num<<1,ans); 110 else if(minn[num<<1|1]<=x&&x<=maxx[num<<1|1]) 111 ask(L,R,mid+1,r,x,num<<1|1,ans); 112 } 113 else 114 { 115 ask(L,R,l,mid,x,num<<1,ans); 116 ask(L,R,mid+1,r,x,num<<1|1,ans); 117 } 118 } 119 inline int get(int u,int d) 120 { 121 int ans=-1; 122 ask(dfn[u],low[u],1,n,dep[u]+d,1,ans); 123 return ans; 124 } 125 struct query 126 { 127 int d,id; 128 }; 129 vector<query>Q[maxn]; 130 void dfs2(int u,int F,int pos,int P,int p) 131 { 132 if(u!=1) 133 { 134 int len=dep[u]-dep[pos]; 135 int g=jump(u,len-1); 136 for(int i=0;i<Q[u].size();++i) 137 { 138 int d=Q[u][i].d,id=Q[u][i].id; 139 if(d<=len) 140 ans[id]=jump(u,d); 141 else if(P!=0) 142 { 143 ask(dfn[P],low[P],1,n,dep[pos]+d-len,1,ans[id]); 144 } 145 } 146 } 147 int pos1=0,pos2=0,d1=0,d2=0; 148 for(int i=head[u];i;i=E[i].next) 149 { 150 int v=E[i].to; 151 if(v==F) 152 continue; 153 int d=1+maxd[v]; 154 if(d>d1) 155 { 156 d2=d1,pos2=pos1; 157 d1=d,pos1=v; 158 } 159 else if(d>d2) 160 d2=d,pos2=v; 161 } 162 int d3=dep[u]-dep[pos]+p; 163 for(int i=head[u];i;i=E[i].next) 164 { 165 int v=E[i].to; 166 if(v==F) 167 continue; 168 if(pos1==v) 169 { 170 if(d3>=d2) 171 dfs2(v,u,pos,P,p); 172 else 173 dfs2(v,u,u,pos2,d2); 174 } 175 else 176 { 177 if(d3>=d1) 178 dfs2(v,u,pos,P,p); 179 else 180 dfs2(v,u,u,pos1,d1); 181 } 182 } 183 } 184 inline void solveUp() 185 { 186 int pos1=0,pos2=0,d1=0,d2=0; 187 for(int i=head[1];i;i=E[i].next) 188 { 189 int v=E[i].to; 190 int d=1+maxd[v]; 191 if(d>d1) 192 { 193 d2=d1,pos2=pos1; 194 d1=d,pos1=v; 195 } 196 else if(d>d2) 197 d2=d,pos2=v; 198 } 199 for(int i=head[1];i;i=E[i].next) 200 { 201 int v=E[i].to; 202 if(v==pos1) 203 dfs2(v,1,1,pos2,d2); 204 else 205 dfs2(v,1,1,pos1,d1); 206 } 207 } 208 int main() 209 { 210 freopen("hunting.in","r",stdin); 211 freopen("hunting.out","w",stdout); 212 ios::sync_with_stdio(false); 213 n=read(),q=read(); 214 for(int i=2;i<=n;++i) 215 { 216 int x=read(),y=read(); 217 add(x,y); 218 add(y,x); 219 } 220 dfs(1,1,0); 221 build(1,n,1); 222 for(int i=1;i<=q;++i) 223 { 224 ans[i]=-1; 225 int u=read(),d1=read(),v=read(),d2=read(); 226 int w=lca(u,v); 227 int d=dep[u]+dep[v]-2*dep[w]; 228 int x=d1-d2+d; 229 if(d1+d2<d||x<0||(x&1)||x>d*2) 230 continue; 231 x/=2; 232 int up=dep[u]-dep[w]; 233 if(u==v) 234 { 235 if(d1!=d2) 236 continue; 237 if(d1==0) 238 { 239 ans[i]=u; 240 continue; 241 } 242 ask(dfn[u],low[u],1,n,dep[u]+d1,1,ans[i]); 243 if(u!=1) 244 Q[u].push_back((query){d1,i}); 245 } 246 else if(x==0) 247 { 248 if(d1==0) 249 { 250 ans[i]=u; 251 continue; 252 } 253 if(dfn[v]<=dfn[u]&&low[u]<=low[v]) 254 ask(dfn[u],low[u],1,n,dep[u]+d1,1,ans[i]); 255 else if(dfn[u]<=dfn[v]&&low[v]<=low[u]) 256 { 257 int g=jump(v,dep[v]-dep[u]-1); 258 ask(dfn[u],dfn[g]-1,1,n,dep[u]+d1,1,ans[i]); 259 ask(low[g]+1,low[u],1,n,dep[u]+d1,1,ans[i]); 260 if(u!=1&&dfn[u]<=dfn[v]&&low[v]<=low[u]) 261 Q[u].push_back((query){d1,i}); 262 } 263 else 264 ask(dfn[u],low[u],1,n,dep[u]+d1,1,ans[i]); 265 } 266 else if(x==d) 267 { 268 if(d2==0) 269 { 270 ans[i]=v; 271 continue; 272 } 273 if(dfn[u]<=dfn[v]&&low[v]<=low[u]) 274 ask(dfn[v],low[v],1,n,dep[v]+d2,1,ans[i]); 275 else if(dfn[v]<=dfn[u]&&low[u]<=low[v]) 276 { 277 int g=jump(u,dep[u]-dep[v]-1); 278 ask(dfn[v],dfn[g]-1,1,n,dep[v]+d2,1,ans[i]); 279 ask(low[g]+1,low[v],1,n,dep[v]+d2,1,ans[i]); 280 if(v!=1&&dfn[v]<=dfn[u]&&low[u]<=low[v]) 281 Q[v].push_back((query){d2,i}); 282 } 283 else 284 ask(dfn[v],low[v],1,n,dep[v]+d2,1,ans[i]); 285 } 286 else if(x==up) 287 { 288 int g1=jump(u,dep[u]-dep[w]-1); 289 int g2=jump(v,dep[v]-dep[w]-1); 290 int l1=dfn[g1],r1=low[g1]; 291 int l2=dfn[g2],r2=low[g2]; 292 if(l1>l2) 293 swap(l1,l2),swap(r1,r2); 294 if(w==u) 295 { 296 ask(dfn[w],dfn[g2]-1,1,n,dep[w]+d1-x,1,ans[i]); 297 ask(low[g2]+1,low[w],1,n,dep[w]+d1-x,1,ans[i]); 298 } 299 else if(w==v) 300 { 301 ask(dfn[w],dfn[g1]-1,1,n,dep[w]+d1-x,1,ans[i]); 302 ask(low[g1]+1,low[w],1,n,dep[w]+d1-x,1,ans[i]); 303 } 304 else 305 { 306 ask(dfn[w],l1-1,1,n,dep[w]+d1-x,1,ans[i]); 307 ask(r1+1,l2-1,1,n,dep[w]+d1-x,1,ans[i]); 308 ask(r2+1,low[w],1,n,dep[w]+d1-x,1,ans[i]); 309 } 310 if(w!=1) 311 Q[w].push_back((query){d1-x,i}); 312 } 313 else if(x<up) 314 { 315 int g=jump(u,x-1); 316 int now=fa[g][0]; 317 ask(dfn[now],dfn[g]-1,1,n,dep[now]+d1-x,1,ans[i]); 318 ask(low[g]+1,low[now],1,n,dep[now]+d1-x,1,ans[i]); 319 } 320 else 321 { 322 x=d-x; 323 int g=jump(v,x-1); 324 int now=fa[g][0]; 325 ask(dfn[now],dfn[g]-1,1,n,dep[now]+d2-x,1,ans[i]); 326 ask(low[g]+1,low[now],1,n,dep[now]+d2-x,1,ans[i]); 327 } 328 } 329 solveUp(); 330 for(int i=1;i<=q;++i) 331 write(ans[i]); 332 return 0; 333 } 334 /* 335 11 1 336 1 2 337 2 3 338 1 4 339 4 5 340 4 6 341 5 7 342 5 8 343 6 9 344 9 10 345 10 11 346 347 */
2.
有一张 𝑛 个点,𝑚 条边的无向图,你想选出一个非空点集,使得仅保留这个点集中的点和两个端点都在这个点集里的边后得到的图是连通的。问合法的点集数对2取模。n<=50,一条边两个点的编号差小于等于14。
对于一个非空点集,我们计算2的联通块次方。可以发现,若联通块个数大于等于2那么对4取模就是0。
那么相当于给每一个联通块进行染色,统计总方案数,若对4取模为2,答案为1,否则为0。
3.问一个字符串中所有长度为m的字符串,有多少个长度为m的字符串和它相似。相似定义为两个字符串至多有1个位置上的字符不同。
相似可以变为最长公共前缀+最长公共后缀>=m-1。这相当于给出两个树,问对于一个点u,有多少个点使得dep1[lca(u,v)]+dep2[lca(u,v)]>=m-1。
树上启发式合并即可。我想不会有人能看懂,就不说了。