| |
| |
| |
| #include<bits/stdc++.h> |
| using namespace std; |
| namespace Octane { |
| |
| #define OCTANE |
| #define BUFFER_SIZE 100000 |
| #define ll long long |
| #define db double |
| #define ldb long double |
| char ibuf[100000], obuf[100000], *p1=ibuf,*p2=ibuf,*p3=obuf; |
| #ifdef ONLINE_JUDGE |
| #define getchar() ((p1==p2) and (p2=(p1=ibuf)+fread(ibuf,1,\ |
| BUFFER_SIZE,stdin),p1==p2)?(EOF):(*p1++)) |
| #define putchar(x) ((p3==obuf+BUFFER_SIZE) && (fwrite(obuf,\ |
| p3-obuf,1,stdout),p3=obuf),*p3++=x) |
| #endif |
| #define isdigit(ch) (ch>47&&ch<58) |
| #define isspace(ch) (ch<=32&&ch!=EOF) |
| #define isseen(ch) (ch>32) |
| struct Octane_t{~Octane_t(){fwrite(obuf,p3-obuf, 1, stdout); |
| }bool flag=false;operator bool(){return flag;} }io; template |
| <typename T>inline T read(){T s=0; int w = 1; char ch; while |
| (ch=getchar(), !isdigit(ch)&&(ch!=EOF))if(ch == '-') w = -1; |
| if(ch == EOF) return 0; while(isdigit(ch)) s = s*10+ch-48,ch |
| =getchar(); return s *= w; } template<typename T>inline bool |
| read(T &s) { s = 0; int w = 1; char ch; while(ch = getchar() |
| ,!isdigit(ch)&&(ch!=EOF))if(ch == '-') w = -1; if(ch == EOF) |
| return false;while(isdigit(ch))s = s*10+ch-48, ch=getchar(); |
| return s*=w,true;}inline bool read(char &s){while(s= getchar |
| (), isspace(s)); return s != EOF; } inline bool read(char *s |
| ){char ch=getchar();while(isspace(ch))ch= getchar();if(ch == |
| EOF)return false;while(isseen(ch)) *s++ = ch, ch= getchar(); |
| *s='\000';return true;}template<typename T> void printv(T a) |
| {if(a== 0){ putchar('0'); return void(); }static char st[65] |
| ; int top = 0; if (a < 0) putchar ('-'), a = - a; while(a)st |
| [++top]='0'+a%10,a/=10;while(top)putchar(st[top--]);} inline |
| void printv(char c){putchar(c);}inline void printv(char *s){ |
| for(int i=0;s[i];i++)putchar(s[i]);}inline void printv(const |
| char *s){ for(int i=0;s[i];i++) putchar(s[i]); } inline void |
| printv(bool a){ if(a != 0)putchar('1'); else putchar('0'); } |
| #ifdef _GLIBCXX_STRING |
| inline bool read(std::string& s) { s = ""; char ch; while(ch |
| =getchar(), isspace(ch)); if(ch == EOF) return false; while( |
| !isspace(ch)) s+=ch,ch=getchar(); return true; } inline bool |
| getline(Octane_t &io,std::string s){s="";char ch= getchar(); |
| if(ch==EOF)return false;while(ch!='\n' and ch !=EOF)s+=ch,ch |
| =getchar();return true;}inline void printv(const std::string |
| &a){for(auto i = a.begin(); i != a.end(); ++i) putchar(*i);} |
| #endif |
| template<typename T>inline void print(const char *p,T first) |
| { int n = strlen(p) - 1; for(int i = 0; i <= n; i++) { if(p[ |
| i] == '`') { putchar(p[++ i]); continue; } else if ( p[i] == |
| '{'){printv(first); i++; continue; } else putchar(p[i]); } } |
| #if __cplusplus >= 201103L |
| template<typename T,typename... T1>inline int read(T& a, T1& |
| ...other){return read(a)+read(other...); } inline void print |
| (const char *p) { printv(p); }template<typename T1, typename |
| ... T2>void print(const char*p, T1 first, T2 ...other) { int |
| n=strlen(p)-1; for(int i = 0; i <= n; i++) { if(p[i] == '`') |
| {putchar(p[++i]);continue;}else if(p[i]=='{'){printv(first); |
| print(p+i+2,other...);return void();}else putchar(p[i]); } } |
| #endif |
| template <typename T> Octane_t& operator >> (Octane_t &io, T |
| &b){return io.flag=read(b),io;}Octane_t& operator>>(Octane_t |
| &io, char *b){return io.flag=read(b), io;} template<typename |
| T>Octane_t&operator<<(Octane_t&io,T b){return printv(b),io;} |
| #define cout io |
| #define cin io |
| #define endl '\n' |
| #undef ll |
| #undef db |
| #undef ldb |
| } using namespace Octane; |
| |
| |
| typedef pair<int,int> pii; |
| #define mk make_pair |
| #define ps push_back |
| #define fi first |
| #define se second |
| const int N=1e5+10,inf=0x3f3f3f3f; |
| |
| int siz[N],fa[N],dep[N],dfn[N],son[N],top[N],tot; |
| int n,m,hd[N],cnt; |
| struct jj{ |
| int to,next; |
| }bi[N<<1]; |
| inline void ad(int x,int y){bi[++cnt]={y,hd[x]},hd[x]=cnt,bi[++cnt]={x,hd[y]},hd[y]=cnt;} |
| inline void dfs1(int x,int f){ |
| dep[x]=dep[f]+1;fa[x]=f;siz[x]=1; |
| for(int i=hd[x];i;i=bi[i].next){ |
| int j=bi[i].to; |
| if(j!=f){ |
| dfs1(j,x);siz[x]+=siz[j]; |
| siz[j]>siz[son[x]]?son[x]=j:0; |
| } |
| } |
| } |
| inline void dfs2(int x,int zu){ |
| top[x]=zu;dfn[x]=++tot; |
| if(son[x])dfs2(son[x],zu); |
| for(int i=hd[x];i;i=bi[i].next){ |
| int j=bi[i].to; |
| if(!dfn[j])dfs2(j,j); |
| } |
| } |
| int sz[N<<2],tag[N<<2]; |
| bool t0[N<<2]; |
| inline void qing(int k,int l,int r,int L,int R){ |
| if(L<=l&&r<=R)return (void)(sz[k]=0,t0[k]=1,tag[k]=0); |
| int mid=l+r>>1; |
| if(t0[k])sz[k<<1]=sz[k<<1|1]=0,t0[k<<1]=t0[k<<1|1]=1,tag[k<<1]=tag[k<<1|1]=0,t0[k]=0; |
| if(tag[k]){sz[k<<1]+=tag[k]*(mid-l+1),sz[k<<1|1]+=tag[k]*(r-mid),tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k],tag[k]=0;} |
| if(L<=mid)qing(k<<1,l,mid,L,R); |
| if(R>mid)qing(k<<1|1,mid+1,r,L,R); |
| sz[k]=sz[k<<1]+sz[k<<1|1]; |
| } |
| inline void add(int k,int l,int r,int L,int R){ |
| if(L<=l&&r<=R)return (void)(sz[k]+=(r-l+1),++tag[k]); |
| int mid=l+r>>1; |
| if(t0[k])sz[k<<1]=sz[k<<1|1]=0,t0[k<<1]=t0[k<<1|1]=1,tag[k<<1]=tag[k<<1|1]=0,t0[k]=0; |
| if(tag[k]){sz[k<<1]+=tag[k]*(mid-l+1),sz[k<<1|1]+=tag[k]*(r-mid),tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k],tag[k]=0;} |
| if(L<=mid)add(k<<1,l,mid,L,R); |
| if(R>mid)add(k<<1|1,mid+1,r,L,R); |
| sz[k]=sz[k<<1]+sz[k<<1|1]; |
| } |
| inline int ask(int k,int l,int r,int L,int R){ |
| if(L<=l&&r<=R)return sz[k]; |
| int mid=l+r>>1,ans=0; |
| if(t0[k])sz[k<<1]=sz[k<<1|1]=0,t0[k<<1]=t0[k<<1|1]=1,tag[k<<1]=tag[k<<1|1]=0,t0[k]=0; |
| if(tag[k]){sz[k<<1]+=tag[k]*(mid-l+1),sz[k<<1|1]+=tag[k]*(r-mid),tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k],tag[k]=0;} |
| if(L<=mid)ans=ask(k<<1,l,mid,L,R); |
| if(R>mid)ans+=ask(k<<1|1,mid+1,r,L,R); |
| return ans; |
| } |
| set<pii> s; |
| int man=0; |
| inline void add(int x,int y){ |
| vector<pii> v,vdo; |
| while(top[x]!=top[y]){ |
| if(dep[top[x]]>dep[top[y]])swap(x,y); |
| if(son[y])qing(1,1,n,dfn[top[y]],dfn[son[y]]); |
| else qing(1,1,n,dfn[top[y]],dfn[y]); |
| auto i1=s.lower_bound({dfn[top[y]],0}),i2=s.upper_bound({dfn[y],n}); |
| for(auto i=i1;i!=i2;++i){ |
| qing(1,1,n,(*i).se,(*i).se); |
| } |
| if(i1!=i2)s.erase(i1,i2); |
| vdo.ps({dfn[top[y]],dfn[y]}); |
| |
| v.ps({dfn[fa[top[y]]],dfn[top[y]]}); |
| y=fa[top[y]]; |
| } |
| if(dep[x]>dep[y])swap(x,y); |
| if(son[y])qing(1,1,n,dfn[x],dfn[son[y]]); |
| else qing(1,1,n,dfn[x],dfn[y]); |
| auto i1=s.lower_bound({dfn[x],0}),i2=s.upper_bound({dfn[y],n}); |
| for(auto i=i1;i!=i2;++i){ |
| qing(1,1,n,(*i).se,(*i).se); |
| } |
| if(i1!=i2)s.erase(i1,i2); |
| if(x!=y)add(1,1,n,dfn[x]+1,dfn[y]); |
| for(auto i:vdo){ |
| add(1,1,n,i.fi,i.se); |
| } |
| s.insert(v.begin(), v.end()); |
| } |
| inline int ask(int x,int y){ |
| int ans=0; |
| while(top[x]!=top[y]){ |
| if(dep[top[x]]>dep[top[y]])swap(x,y); |
| ans+=ask(1,1,n,dfn[top[y]],dfn[y]); |
| y=fa[top[y]]; |
| } |
| if(dep[x]>dep[y])swap(x,y); |
| if(x!=y)ans+=ask(1,1,n,dfn[x]+1,dfn[y]); |
| return ans; |
| } |
| #define fl(x) (fill(x+1,x+1+n,0)) |
| signed main(){ |
| #ifndef ONLINE_JUDGE |
| freopen("in.in","r",stdin); |
| freopen("out.out","w",stdout); |
| #endif |
| |
| int t; |
| cin>>t; |
| |
| |
| while(t--){ |
| cin>>n>>m; |
| if(t!=2){qing(1,1,n,1,n);fill(hd+1,hd+1+n,0);cnt=0;tot=0;fill(son+1,son+1+n,0);s.clear();fl(dfn);} |
| for(int i=1,x,y;i<n;++i){ |
| cin>>x>>y; |
| ad(x,y); |
| } |
| dfs1(1,0);dfs2(1,1); |
| for(int i=1,op,x,y;i<=m;++i){ |
| cin>>op>>x>>y; |
| if(op==1)add(x,y); |
| else { |
| cout<<ask(x,y)<<'\n'; |
| |
| } |
| } |
| } |
| |
| |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)