BZOJ1146: [CTSC2008]网络管理Network

。。。我居然调试了一个下午  因为一个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;
}


你可能感兴趣的:(bzoj,树套树)