。。。我居然调试了一个下午 因为一个else 一个if。。。。
果然自己太弱
听Claris说这一题可以转化为DFS序然后容斥可以直接变成logn*logn*n 只能膜拜
我的是logn*logn*logn*logn*n
然后Jrmz说,这还不如暴力。。。。。
反正就是很普通的一道树剖 然后在链上找k大值用树套树 由于只会外层线段树维护区间的写法 于是就打了3个log的
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> using namespace std; char c; inline void read(int &a) {a=0;do c=getchar();while(c<'0'||c>'9'); while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();} struct Node {Node *f,*lc,*rc;int size,con,data;inline bool l(){return this->f->lc==this;}}*empty; Node w[5000002]; Node*stack[5000002]; int con; inline void Begin() { empty=new Node;empty->lc=empty->rc=empty;empty->size=0; con=5000000; for(int i=0;i<=con;i++) stack[i]=&w[i]; } inline Node *New_Node(){Node *tp=stack[con--];tp->lc=tp->rc=empty;tp->size=tp->con=1;tp->f=tp; if(con==4976747) tp->con--,tp->con++; if(tp==w+119441952) tp->con++,tp->con--; return tp;} inline void del(Node *a){stack[++con]=a;} inline void push_down(Node *a) { a->size=a->con+a->lc->size+a->rc->size; if(a->size<0) a->size=a->size-1+1; } inline void lc(Node *a) { Node *fff; if(a->f->f==a->f) fff=a; else if(a->f->l()) a->f->f->lc=a,fff=a->f->f; else a->f->f->rc=a,fff=a->f->f; a->rc->f=a->f; a->f->lc=a->rc; a->f->f=a; a->rc=a->f; a->f=fff; push_down(a->rc); push_down(a); } inline void rc(Node *a) { Node *fff; if(a->f->f==a->f) fff=a; else if(a->f->l()) a->f->f->lc=a,fff=a->f->f; else a->f->f->rc=a,fff=a->f->f; a->lc->f=a->f; a->f->rc=a->lc; a->f->f=a; a->lc=a->f; a->f=fff; push_down(a->lc); push_down(a); } inline void change(Node *a) {a->l()?lc(a):rc(a);} inline void twicechange(Node *a) {a->l()==a->f->l()?change(a->f):change(a);change(a);} inline void rotato(Node *a,int place); inline int find(Node *a,int k,int place) { if(k>a->lc->size&&k<=a->lc->size+a->con) {rotato(a,place);return a->data;} else if(k>a->lc->size) return find(a->rc,k-a->lc->size-a->con,place); return find(a->lc,k,place); } inline int find_rank(Node *a,int data) { if(a==empty)return 1; if(a->data==data)return a->lc->size+1; else if(a->data>data)return a->lc->size+a->con+find_rank(a->rc,data); return find_rank(a->lc,data); } inline void del(Node *a,int place); inline void delta(Node *a,int data,int place) { if(a->data==data)del(a,place); else if(a->data>data)delta(a->rc,data,place); else delta(a->lc,data,place); } inline void insert(Node *a,int data,int place) { if(a->data==data) {a->con++,rotato(a,place);return ;} if(a->data>data) if(a->rc!=empty) insert(a->rc,data,place); else {Node *tp=New_Node();tp->data=data;tp->f=a;a->rc=tp;rotato(tp,place);} else if(a->lc!=empty) insert(a->lc,data,place); else {Node *tp=New_Node();tp->data=data;tp->f=a;a->lc=tp;rotato(tp,place);} } struct Segement{Node *root;int l,r;Segement(){root=empty;}}Segement_Tree[400001]; void Segement_Build(int place,int l,int r); int Segement_Query(int place,int l,int r,int data) { if(Segement_Tree[place].l>=l&&Segement_Tree[place].r<=r) return find_rank(Segement_Tree[place].root,data); int res=0; if(Segement_Tree[place<<1].r>=l) res+=Segement_Query(place<<1,l,r,data)-1; if(Segement_Tree[place<<1|1].l<=r) res+=Segement_Query(place<<1|1,l,r,data)-1; return res+1; } int Segement_Change(int place,int l,int data) { int dt; if(Segement_Tree[place].l==Segement_Tree[place].r) { dt=Segement_Tree[place].root->data,Segement_Tree[place].root->data=data;return dt;} if(Segement_Tree[place<<1].r>=l) dt=Segement_Change(place<<1,l,data); else dt=Segement_Change(place<<1|1,l,data); insert(Segement_Tree[place].root,data,place); delta(Segement_Tree[place].root,dt,place); push_down(Segement_Tree[place].root); return dt; } struct Chain{int other;Chain*next;Chain(){next=NULL;}}*Head[100001]; int f[100001],size[100001],deep[100001],data[100001]; int Heavy_Son[100001],Heavy_Chain_Begin[100001],Heavy_Chain_End[100001],Heavy_Chain_Node[100001],Heavy_Chain_Place[100001]; void dfs(int u) { size[u]++; Heavy_Son[u]=0; for(Chain *tp=Head[u];tp;tp=tp->next) if(tp->other!=f[u]) { deep[tp->other]=deep[u]+1; f[tp->other] =u; dfs(tp->other); if(size[tp->other]>size[Heavy_Son[u]])Heavy_Son[u]=tp->other; size[u]+=size[tp->other]; } } int ccc; int LCA(int u,int v) { while(Heavy_Chain_Begin[u]!=Heavy_Chain_Begin[v]) if(deep[Heavy_Chain_Node[Heavy_Chain_Begin[u]]]<=deep[Heavy_Chain_Node[Heavy_Chain_Begin[v]]]) v=f[Heavy_Chain_Node[Heavy_Chain_Begin[v]]]; else u=f[Heavy_Chain_Node[Heavy_Chain_Begin[u]]]; return deep[u]>deep[v]?v:u; } int cnt; void dfs(int u,int p) { Heavy_Chain_Begin[u]=p; Heavy_Chain_Place[u]=++cnt; Heavy_Chain_Node[cnt]=u; if(Heavy_Son[u]) { dfs(Heavy_Son[u],p); for(Chain *tp=Head[u];tp;tp=tp->next) if(tp->other!=Heavy_Son[u]&&tp->other!=f[u]) dfs(tp->other,cnt+1); } Heavy_Chain_End[u]=cnt; } int n; inline void Query(int uu,int vv,int k) { int l=k,r=n,mid,data,rank,u,v; int ff=LCA(uu,vv); if(1+deep[uu]+deep[vv]-((deep[ff])<<1)<k) {puts("invalid request!");return;} while(l<(r-1)) { mid=(l+r)>>1; u=uu,v=vv; rank=0; data=find(Segement_Tree[1].root,mid,1); while(Heavy_Chain_Begin[u]!=Heavy_Chain_Begin[v]) if(deep[Heavy_Chain_Node[Heavy_Chain_Begin[u]]]<=deep[Heavy_Chain_Node[Heavy_Chain_Begin[v]]]) rank+=Segement_Query(1,Heavy_Chain_Begin[v],Heavy_Chain_Place[v],data)-1,v=f[Heavy_Chain_Node[Heavy_Chain_Begin[v]]]; else rank+=Segement_Query(1,Heavy_Chain_Begin[u],Heavy_Chain_Place[u],data)-1,u=f[Heavy_Chain_Node[Heavy_Chain_Begin[u]]]; rank+=Segement_Query(1,Heavy_Chain_Place[deep[u]<deep[v]?u:v],Heavy_Chain_Place[deep[u]<deep[v]?v:u],data)-1; rank++; if(rank>k) r=mid-1; else l=mid; } if(l==r){printf("%d\n",find(Segement_Tree[1].root,l,1));return ;} mid=r; rank=0; u=uu,v=vv; data=find(Segement_Tree[1].root,mid,1); while(Heavy_Chain_Begin[u]!=Heavy_Chain_Begin[v]) if(deep[Heavy_Chain_Node[Heavy_Chain_Begin[u]]]<=deep[Heavy_Chain_Node[Heavy_Chain_Begin[v]]]) rank+=Segement_Query(1,Heavy_Chain_Begin[v],Heavy_Chain_Place[v],data)-1,v=f[Heavy_Chain_Node[Heavy_Chain_Begin[v]]]; else rank+=Segement_Query(1,Heavy_Chain_Begin[u],Heavy_Chain_Place[u],data)-1,u=f[Heavy_Chain_Node[Heavy_Chain_Begin[u]]]; rank+=Segement_Query(1,Heavy_Chain_Place[deep[u]<deep[v]?u:v],Heavy_Chain_Place[deep[u]<deep[v]?v:u],data)-1; rank++; if(rank>k) {printf("%d\n",find(Segement_Tree[1].root,l,1));return ;} printf("%d\n",data); } inline void change(int u,int data) {Segement_Change(1,Heavy_Chain_Place[u],data);} inline void ADD(int u,int v) {Chain *tp =new Chain; tp->other=v; tp->next=Head[u]; Head[u]=tp;} int main() { int q,a,b; Begin(); read(n),read(q); for(int i=1;i<=n;i++) read(data[i]); for(int i=2;i<=n;i++) read(a),read(b),ADD(a,b),ADD(b,a); f[1]=1; dfs(1); dfs(1,1); Segement_Build(1,1,n); int k; while(q--) { read(k); if(k==0)read(a),read(b),change(a,b); else read(a),read(b),Query(a,b,k); } return 0; } inline void del(Node *a,int place) { rotato(a,place); if(a->con>1) {a->con--;return;} if(a->lc!=empty){Segement_Tree[place].root=a->lc; } while(a->lc!=empty||a->rc!=empty) if(a->lc!=empty)lc(a->lc); else rc(a->rc); (a->l()?a->f->lc:a->f->rc)=empty; rotato(a->f,place); del(a); } void print(Node *a) { if(a->lc!=empty)print(a->lc); printf("data:%d size:%d con:%d\n",a->data,a->size,a->con); if(a->rc!=empty)print(a->rc); } void Segement_Build(int place,int l,int r) { if(l==r) { Segement_Tree[place].l=l; Segement_Tree[place].r=r; Segement_Tree[place].root=New_Node(); Segement_Tree[place].root->f=Segement_Tree[place].root; Segement_Tree[place].root->data=data[Heavy_Chain_Node[l]]; Segement_Tree[place].root->con=1; Segement_Tree[place].root->size=1; return; } Segement_Tree[place].l=l; Segement_Tree[place].r=r; Segement_Tree[place].root=New_Node(); Segement_Tree[place].root->f=Segement_Tree[place].root; Segement_Tree[place].root->data=data[Heavy_Chain_Node[l]]; Segement_Tree[place].root->con=1; Segement_Tree[place].root->size=1; Segement_Build(place<<1,l,(l+r)>>1); Segement_Build(place<<1|1,((l+r)>>1)+1,r); for(int i=l+1;i<=r;i++) insert(Segement_Tree[place].root,data[Heavy_Chain_Node[i]],place); } inline void rotato(Node *a,int place) { while(a->f->f!=a->f)twicechange(a); while(a->f!=a)change(a);Segement_Tree[place].root=a; }