。。。我居然调试了一个下午 因为一个else 一个if。。。。
果然自己太弱
听Claris说这一题可以转化为DFS序然后容斥可以直接变成logn*logn*n 只能膜拜
我的是logn*logn*logn*logn*n
然后Jrmz说,这还不如暴力。。。。。
反正就是很普通的一道树剖 然后在链上找k大值用树套树 由于只会外层线段树维护区间的写法 于是就打了3个log的
#include
#include
#include
#include
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)>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]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]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;
}