BZOJ3626: [LNOI2014]LCA

想到离线之后就很裸了。。。

我承认自己是SB  一开始还没想到。。。。

还有。。今天每次提交都会忘了删文件。。。。。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
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();
}
const
   int mod=201314;
struct Segement{
	int l,r,data;
	int flag;
}Segement_Tree[1000001];


void Segement_Tree_Build(int place,int l,int r)
{
	Segement_Tree[place].r=r;
	Segement_Tree[place].l=l;
	if(l^r)
	    Segement_Tree_Build(place<<1,l,(l+r)>>1), Segement_Tree_Build(place<<1|1,((l+r)>>1)+1,r);
    Segement_Tree[place].flag=0;
    Segement_Tree[place].data=0;
}
inline void Segement_Tree_Pushdown(int place)
{
	Segement_Tree[place].data+=(Segement_Tree[place].r-Segement_Tree[place].l+1)*Segement_Tree[place].flag;
    Segement_Tree[place].data%=mod;
	if(Segement_Tree[place].l^Segement_Tree[place].r)
	      Segement_Tree[place<<1].flag+=Segement_Tree[place].flag,Segement_Tree[place<<1].flag%=mod, Segement_Tree[place<<1|1].flag+=Segement_Tree[place].flag, Segement_Tree[place<<1|1].flag%=mod;
    Segement_Tree[place].flag=0;
}

int Segement_Tree_Query(int place,int l,int r)
{
	if(Segement_Tree[place].flag)
       Segement_Tree_Pushdown(place);
    if(l<=Segement_Tree[place].l&&r>=Segement_Tree[place].r)
       return Segement_Tree[place].data;
    int data=0;
    if(l<=Segement_Tree[place<<1].r)
        data+=Segement_Tree_Query(place<<1,l,r);
    if(r>=Segement_Tree[place<<1|1].l)
        data+=Segement_Tree_Query(place<<1|1,l,r);
    return data%mod;
}

void Segement_Tree_Add(int place,int l,int r)//1
{
	if(l<=Segement_Tree[place].l&&r>=Segement_Tree[place].r)
      {Segement_Tree[place].flag++;Segement_Tree[place].flag%=mod;return ;}
    Segement_Tree[place].data+=(min(r,Segement_Tree[place].r)-max(l,Segement_Tree[place].l)+1);    
    if(l<=Segement_Tree[place<<1].r)
       Segement_Tree_Add(place<<1,l,r);
    if(r>=Segement_Tree[place<<1|1].l)
       Segement_Tree_Add(place<<1|1,l,r);
}

int Heavy_Chain_Begin[1000001],Heavy_Chain_Place[1000001],Heavy_Chain_End[1000001],Heavy_Chain_Node[1000001];
int Heavy_Con,Heavy_Son[1000001];
struct Chain
{
	int other;
	Chain *next;
	Chain(){next=NULL;}
}*Son[1000001],*Head[1000001];
int f[1000001];
int Con[1000001];
int DFS1(int u)
{
        Chain *ad;
    	Con[u]++;
    	Heavy_Son[u]=0;
    	for(Chain *tp=Head[u];tp;tp=tp->next)
    	if(tp->other!=f[u])
		{
            f[tp->other]=u;
            ad=new Chain;
            ad->other=tp->other;
            ad->next=Son[u];
            Son[u]=ad;
            DFS1(tp->other);
            if(Con[tp->other]>Con[Heavy_Son[u]])
                Heavy_Son[u]=tp->other;
            Con[u]+=Con[tp->other];
		}
}

int DFS2(int u,int f)
{
	Heavy_Chain_Begin[u]=f;
	Heavy_Chain_Place[u]=++Heavy_Con;
	Heavy_Chain_Node[Heavy_Con]=u;
	
	if(Heavy_Son[u])
	   {
	      DFS2(Heavy_Son[u],f);
	      for(Chain *tp=Son[u];tp;tp=tp->next)
	         if(tp->other!=Heavy_Son[u])
	             DFS2(tp->other,Heavy_Con+1);
	   } 
	Heavy_Chain_End[u]=Heavy_Con;
}
inline void addside(int a,int b)
{
  Chain *tp=new Chain;tp->next=Head[a],tp->other=b;
  Head[a]=tp;
}

struct oper
{
	bool end;
	int place;
	int num;
	int z;
	int ans;
	inline friend bool operator <(oper a,oper b)
	{	return a.place<b.place;}
}line[1000001];
inline bool cmp(const oper &a,const oper &b)
{
	return a.num<b.num||(a.num==b.num&&a.end);
}

inline void Add(int u)
{
    if(u==0)
       return ;
	while(Heavy_Chain_Begin[u]!=1)
	 {
	 	Segement_Tree_Add(1,Heavy_Chain_Begin[u],Heavy_Chain_Place[u]);
	    u=f[Heavy_Chain_Node[Heavy_Chain_Begin[u]]];
	 }
	Segement_Tree_Add(1,Heavy_Chain_Begin[u],Heavy_Chain_Place[u]);
}

inline int Query(int u)
{
	int res=0;
    if(u==0)
       return 0;
	while(Heavy_Chain_Begin[u]!=1)
	 {
	 	res+=Segement_Tree_Query(1,Heavy_Chain_Begin[u],Heavy_Chain_Place[u]);
	    u=f[Heavy_Chain_Node[Heavy_Chain_Begin[u]]];
	 }
	res+=Segement_Tree_Query(1,Heavy_Chain_Begin[u],Heavy_Chain_Place[u]); 
	return res;
}
int main()
{

	int i,j,k,l,n,m,r;
	read(n),read(m);
	for(i=2;i<=n;i++)
	    read(f[i]),f[i]++,addside(f[i],i),addside(i,f[i]);
	DFS1(1),DFS2(1,1);
	Segement_Tree_Build(1,1,Heavy_Con);
	for(i=1;i<=m;i++) 
	  {
	  	read(l),read(r);
	  	line[(i<<1)-1].end=false;
	  	line[(i<<1)-1].place=r+1;
	  	line[i<<1].end=true;
	  	line[i<<1].place=l;
	    line[(i<<1)-1].num=line[(i<<1)].num=i;
	    read(k);
		line[(i<<1)-1].z=line[(i<<1)].z=k+1;
	  }
	sort(line+1,line+1+(m<<1));
	int last=1;
	m<<=1;
	for(i=1;i<=m;i++)
	  {
	  	if(line[i].place>=last)
		     for(last;last<=line[i].place;last++) 
		         Add(last);
		line[i].ans=Query(line[i].z)%mod;
	  }
	m>>=1;
	sort(line+1,line+1+(m<<1),cmp);
	for(i=1;i<=m;i++)
	    printf("%d\n",(mod+(line[i<<1].ans-line[(i<<1)-1].ans)%mod)%mod);
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值