【codevs】4633 树链剖分入门

之前的模板错了一个地方。。。调的时候怎么也不行。。。

更新&&求解都需要在树链上爬一边。。。


#include<iostream>
#include<cstdio>
#define MAXN 249999 
#define LL long long 
using namespace std;

//use of main
LL n,m;
//use of pre_star
struct edge
{
  LL next,to;
  edge(){next=to=0;}       
}len[MAXN*2];
LL fst[MAXN*2]={0};
LL num=0;
inline void add(LL u,LL v)
{len[++num].next=fst[u],len[num].to=v,fst[u]=num;}
//use of SP
LL fa[MAXN]={0},son[MAXN]={0};
LL top[MAXN]={0},size[MAXN]={0},dep[MAXN]={0};
LL po[MAXN]={0};
LL cnt=0;
//use of tree
struct tree
{
  LL sum,add;
  tree(){sum=add=0;}       
}use[MAXN*4];

inline LL lc(LL x){return x<<1;}
inline LL rc(LL x){return x<<1|1;}
inline void swap(LL &a,LL &b){LL t=a;a=b;b=t;}

void dfs_1(LL x,LL deep)
{
  dep[x]=deep;
  size[x]=1,son[x]=0;
  for(LL i=fst[x];i;i=len[i].next)   
    if(len[i].to!=fa[x])
    {
      fa[len[i].to]=x;
      dfs_1(len[i].to,deep+1);
      size[x]+=size[len[i].to]; 
      if(size[len[i].to]>size[son[x]])
        son[x]=len[i].to;
    } 
}

void dfs_2(LL x,LL pre)
{
  top[x]=pre,po[x]=++cnt;
  if(son[x]!=0)dfs_2(son[x],pre);
  for(LL i=fst[x];i;i=len[i].next)
    if(len[i].to!=fa[x]&&len[i].to!=son[x])
      dfs_2(len[i].to,len[i].to);                
}

inline void up(LL x)
{
  use[x].sum=use[lc(x)].sum+use[rc(x)].sum;      
}

inline void down(LL x,LL op,LL ed)
{
  if(use[x].add!=0)
  {
    LL l=lc(x),r=rc(x);
    LL mid=(op+ed)>>1;
    use[l].sum+=use[x].add*(mid-op+1);
    use[r].sum+=use[x].add*(ed-mid);
    use[l].add+=use[x].add;
    use[r].add+=use[x].add;
    use[x].add=0;                 
  }       
}

void update(LL x,LL l,LL r,LL op,LL ed)
{
  if(op<=l&&r<=ed)
  {
    use[x].sum+=(r-l+1);
    use[x].add++;
    return ;                
  }
  down(x,l,r);
  LL mid=(l+r)>>1;
  if(ed<=mid)update(lc(x),l,mid,op,ed);
  else if(op>mid)update(rc(x),mid+1,r,op,ed);
  else update(lc(x),l,mid,op,ed),update(rc(x),mid+1,r,op,ed);
  up(x);
}

LL query(LL x,LL l,LL r,LL op,LL ed)
{
  if(op<=l&&r<=ed)
    return use[x].sum;               
  down(x,l,r);
  LL mid=(l+r)>>1;
  LL ans=0;
  if(ed<=mid)ans+=query(lc(x),l,mid,op,ed);
  else if(op>mid)ans+=query(rc(x),mid+1,r,op,ed);
  else ans+=query(lc(x),l,mid,op,ed)+query(rc(x),mid+1,r,op,ed);
  return ans;
}

void find_sum(LL a,LL b)
{
  LL t1=top[a],t2=top[b];
  while(t1!=t2)
  {
    if(dep[t1]<dep[t2]){swap(t1,t2),swap(a,b);}
    update(1,1,n,po[t1],po[a]);
    a=fa[t1],t1=top[a];    
  }
  if(dep[a]<dep[b])update(1,1,n,po[a],po[b]);
  else update(1,1,n,po[b],po[a]);
}
LL ans_sum(LL a,LL b)
{
  int t1=top[a],t2=top[b];
  LL ans=0;
  while(t1!=t2)
  {
    if(dep[t1]<dep[t2]){swap(a,b),swap(t1,t2);}
    ans+=query(1,1,n,po[t1],po[a]);
    a=fa[t1],t1=top[a];      
  }
  if(dep[a]<dep[b])ans+=query(1,1,n,po[a],po[b]);
  else ans+=query(1,1,n,po[b],po[a]);
  return ans;   
}

int main()
{
  scanf("%I64d",&n);
  LL t1,t2;
  for(int i=1;i<n;i++)
  {
    scanf("%I64d%I64d",&t1,&t2);
    add(t1,t2),add(t2,t1);
  }
  dfs_1(1,1);
  dfs_2(1,1);
//*    
  scanf("%d",&m);
  int k=0;
  for(int i=1;i<=m;i++)
  {
     scanf("%d%I64d%I64d",&k,&t1,&t2);  
     if(k==1)
     {
       find_sum(t1,t2);        
     }
     else if(k==2)
     {
       printf("%lld\n",ans_sum(t1,t2));     
     }
  }
  //*/
    
  //while(1);
  return 0;    
  //1 2 5 3 4 
  /*
                     1(2)
              2(2)       4(1)
        3(1)       5(1)
          
  */  
}



Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值