题目链接:传送门
题目大意:中文题,略
题目思路:树链剖分,区间更新,区间查询。
闲谈: 只想说这道题做的好苦逼。。去长春现场赛之前就没A,回来后又做了2天才A掉,蒟蒻太菜了
这道题也没有想象中那么难,就是代码有点长。。
在查询的时候注意判断端点交界处如果相同则答案-1。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 100005 #define maxn 30010 typedef pair<int,int> PII; typedef long long LL; LL read(){ LL 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<<3)+(x<<1)+ch-‘0‘;ch=getchar();} return x*f; } int n,m,k,sz,L,R; int a[N],mrk[N<<2]; struct Seg{int l,r,v;}seg[N<<2]; int son[N],siz[N],id[N],tid,posi[N]; int top[N],fa[N],dep[N],head[N],hcnt; struct Node{int to,nxt;}node[N<<1]; void dfs1(int u,int f,int deep){ dep[u]=deep,fa[u]=f,siz[u]=1; for(int i=head[u];~i;i=node[i].nxt){ int e=node[i].to; if(e==f)continue; dfs1(e,u,deep+1); siz[u]+=siz[e]; if(!son[u]||siz[son[u]]<siz[e]) son[u]=e; } } void dfs2(int u,int tp){ top[u]=tp,id[u]=++tid,posi[tid]=u; if(!son[u])return;dfs2(son[u],tp); for(int i=head[u];~i;i=node[i].nxt){ int e=node[i].to; if(!id[e])dfs2(e,e); } } void pushdown(int rt){ seg[rt<<1].v=seg[rt<<1|1].v=1; seg[rt<<1].l=seg[rt<<1].r=mrk[rt]; seg[rt<<1|1].l=seg[rt<<1|1].r=mrk[rt]; mrk[rt<<1]=mrk[rt<<1|1]=mrk[rt];mrk[rt]=-1; } int query(int rt,int l,int r){ if(L<=l&&r<=R)return seg[rt].v; int mid=l+r>>1,temp=0,t1=-1,t2=-1; if(~mrk[rt])pushdown(rt); if(L<=mid)t1=seg[rt<<1].r,temp+=query(lson); if(R>mid) t2=seg[rt<<1|1].l,temp+=query(rson); seg[rt].l=seg[rt<<1].l,seg[rt].r=seg[rt<<1|1].r; seg[rt].v=seg[rt<<1].v+seg[rt<<1|1].v-(seg[rt<<1].r==seg[rt<<1|1].l); temp-=(t1==t2&&t1!=-1); return temp; } void update(int rt,int l,int r,int v){ if(L<=l&&r<=R){seg[rt].v=1,seg[rt].l=seg[rt].r=mrk[rt]=v;return;} int mid=l+r>>1; if(~mrk[rt])pushdown(rt); if(L<=mid)update(lson,v); if(R>mid) update(rson,v); seg[rt].l=seg[rt<<1].l,seg[rt].r=seg[rt<<1|1].r; seg[rt].v=seg[rt<<1].v+seg[rt<<1|1].v-(seg[rt<<1].r==seg[rt<<1|1].l); } int findp(int rt,int l,int r,int L){ if(l==r)return seg[rt].l; int mid=l+r>>1,temp; if(~mrk[rt])pushdown(rt); if(L<=mid)return findp(lson,L); else return findp(rson,L); } void lca(int x,int y){ int res=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); L=id[top[x]],R=id[x]; res+=query(1,1,n); L=id[x]; if(findp(1,1,n,id[top[x]])==findp(1,1,n,id[fa[top[x]]]))--res; ///看两端是否相同 x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); L=id[x],R=id[y]; res+=query(1,1,n); printf("%d\n",res); } void change(int x,int y,int v){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); L=id[top[x]],R=id[x]; update(1,1,n,v); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); L=id[x],R=id[y]; update(1,1,n,v); } void build(int rt,int l,int r){ if(l==r){seg[rt].l=seg[rt].r=a[posi[l]],seg[rt].v=1;return;} int mid=l+r>>1; build(lson);build(rson); seg[rt].v=seg[rt<<1].v+seg[rt<<1|1].v-(seg[rt<<1].r==seg[rt<<1|1].l); seg[rt].l=seg[rt<<1].l,seg[rt].r=seg[rt<<1|1].r; } int main(){ int i,j,group,x,y,v; n=read(),m=read();mst(head,-1);mst(mrk,-1); for(i=1;i<=n;++i)a[i]=read(); for(i=1;i<n;++i){ x=read(),y=read(); node[hcnt].to=y;node[hcnt].nxt=head[x],head[x]=hcnt++; node[hcnt].to=x,node[hcnt].nxt=head[y],head[y]=hcnt++; } dfs1(1,1,1);dfs2(1,1);build(1,1,n); char ch; while(m--){ scanf(" %c",&ch); x=read(),y=read(); if(ch==‘Q‘) lca(x,y); else v=read(),change(x,y,v); } return 0; }
时间: 2024-10-29 19:12:21