萌新刚学c++,树剖有人调嘛awa~
查看原帖
萌新刚学c++,树剖有人调嘛awa~
210719
Violet___Evergarden楼主2021/9/21 11:11

过了样例但0分

#include <iostream>
using namespace std;
int n,m,r,p;
const int kMaxN=1e5+1;
struct SLPF//树链
{
  int heavyson;//这个节点的重儿子
  int size,top,newid;//它的子树的大小,这条链的顶部,它的编号(线段树要用)
  int father,deep;//它的父亲和深度
}s[kMaxN*2];
int num;
struct XDS//线段树
{
  int l,r;//它所包括的区间
  int val,add;//它的值和懒标记
}tr[kMaxN*4];
int a[kMaxN];
struct EDGE//存边不用解释
{
  int to,nt;
}e[kMaxN*2];
int cnt,hd[kMaxN];
int zhi[kMaxN];
void Add(int a,int b)
{
  e[++cnt].to=b;
  e[cnt].nt=hd[a];
  hd[a]=cnt;
}
void Build(int where,int l,int r)//建线段树
{
  tr[where].l=l;
  tr[where].r=r;
  if(l==r)
  {
    tr[where].val=zhi[l]%p;
    return;
  }
  int mid=(l+r)/2;
  Build(where*2,l,mid);
  Build(where*2+1,mid+1,r);
  tr[where].val=(tr[where*2].val,tr[where*2+1].val)%p;
}
void Solve(int where)//处理懒标记
{
  tr[where*2+1].val+=tr[where].add*(tr[where*2+1].l-tr[where*2+1].r+1)%p;
  tr[where*2+1].val%=p;
  tr[where*2].val+=tr[where].add*(tr[where*2].l-tr[where*2].r+1)%p;
  tr[where].val%=p;
  tr[where*2+1].add+=tr[where].add;
  tr[where*2+1].add%=p;
  tr[where*2].add+=tr[where].add;
  tr[where*2].add%=p;
  tr[where].add=0;
}
void Update(int where,int l,int r,int z)//线段树的区间更改
{
  if(tr[where].l>=l&&tr[where].r<=r)
  {
    tr[where].val+=(z*(tr[where].l-tr[where].r+1)%p)%p;
    tr[where].val%=p;
    tr[where].add+=z%p;
    tr[where].add%=p;
    return;
  }
  Solve(where);
  int mid=(tr[where].l+tr[where].r)/2;
  if(mid>=l)
  {
    Update(where*2,l,r,z);
  }
  if(mid<r)
  {
    Update(where*2+1,l,r,z);
  }
  tr[where].val=tr[where*2+1].val+tr[where*2].val;
  tr[where].val%=p;
}
int GetSum(int where,int l,int r)//线段树的区间查询
{
  if(tr[where].l>=l&&tr[where].r<=r)
  {
    return tr[where].val;
  }
  Solve(where);
  int mid=(tr[where].l+tr[where].r)/2,sum=0;
  if(mid>=l)
  {
    sum+=GetSum(where*2,l,r);
    sum%=p;
  }
  if(mid<r)
  {
    sum+=GetSum(where*2+1,l,r);
    sum%=p;
  }
  return sum;
}
void dfs1(int now,int last)
{
  s[now].deep=s[last].deep+1;//算深度
  s[now].father=last;//算父亲
  s[now].size=1;//算子树大小
  int howmany=0;
  for(int i=hd[now];i;i=e[i].nt)
  {
    if(e[i].to==last)continue;
    dfs1(e[i].to,now);
    s[now].size+=s[e[i].to].size;
    if(howmany<s[e[i].to].size)//算重儿子
    {
      howmany=s[e[i].to].size;
      s[now].heavyson=e[i].to;
    }
  }
}
void dfs2(int now,int top)
{
  num++;
  s[now].top=top;//算顶部
  s[now].newid=num;//算编号
  zhi[num]=a[now];//点的初始值赋值上来,建线段树要用
  if(s[now].heavyson==0)return;
  dfs2(s[now].heavyson,top);//搜重儿子
  for(int i=hd[now];i;i=e[i].nt)
  {
    if(e[i].to==s[now].father||e[i].to==s[now].heavyson)continue;
    dfs2(e[i].to,e[i].to);//轻儿子开一条新的链
  }
}
void Change(int x,int y,int z)//树链更改(op=1)
{
  while(s[x].top!=s[y].top)//不在同一条链上
  {
    if(s[s[x].top].deep<s[s[y].top].deep)
    {
      swap(x,y);
    }
    Update(1,s[s[x].top].newid,s[x].newid,z);
    x=s[s[x].top].father;//跳出这一条链
  }
  if(s[x].deep>s[y].deep)
  {
    swap(x,y);
  }
  Update(1,s[x].newid,s[y].newid,z);
}
int GetAns(int x,int y)//同理(op=2)
{
  int ans=0;
  while(s[x].top!=s[y].top)
  {
    if(s[s[x].top].deep<s[s[y].top].deep)
    {
      swap(x,y);
    }
    ans+=GetSum(1,s[s[x].top].newid,s[x].newid);
    ans%=p;
    x=s[s[x].top].father;
  }
  if(s[x].deep>s[y].deep)
  {
    swap(x,y);
  }
  ans+=GetSum(1,s[x].newid,s[y].newid);
  ans%=p;
  return ans;
}
void Change2(int x,int z)//op=3
{
  Update(1,s[x].newid,s[x].newid+s[x].size-1,z);
}
int GetAns2(int x)//op=4
{
  return GetSum(1,s[x].newid,s[x].newid+s[x].size-1);
}
signed main()
{
cin>>n>>m>>r>>p;
for(int i=1;i<=n;i++)
{
  cin>>a[i];
}
for(int i=1;i<n;i++)
{
  int a,b;
  cin>>a>>b;
  Add(a,b);
  Add(b,a);
}
dfs1(r,0);
dfs2(r,r);
Build(1,1,n);
for(int i=1;i<=m;i++)
{
  int op;
  cin>>op;
  if(op==1)
  {
    int x,y,z;
    cin>>x>>y>>z;
    Change(x,y,z);
  }
  else if(op==2)
  {
    int x,y;
    cin>>x>>y;
    cout<<GetAns(x,y)%p<<"\n";
  }
  else if(op==3)
  {
    int x,z;
    cin>>x>>z;
    Change2(x,z);
  }
  else if(op==4)
  {
    int x;
    cin>>x;
    cout<<GetAns2(x)%p<<"\n";
  }
}
return 0;
}
2021/9/21 11:11
加载中...