UOJ 418 [2018] Team work triangle - + segment tree merger idea

Topic: http://uoj.ac/problem/418

Read explanations will ......

Good idea is the whole process as a number of "take a little i, value + = w [i], the value - = \ (\ sum w [j] \)" (where i, j children) consisting of operation sequence.

There is a limit sequence "operating in front of the child's father." The anti bit sequence, the operation to "take a little i, value - = w [i], the value + = \ (\ sum w [j] \)", each point is limited to only the position of his father, comparison better to do.

It indicates the operation by a point (x, y). x represents an increment operation ends, y represents the difference between the maximum during the initial value. The reason is "the difference between the initial value" is to merge the two operations in the future; because the initial value is undefined.

  Each point is the initial value (\ (- w [i] + \ sumw [j], \ sumw [j] \)). The combined (a, b), then (c, d) become (a + c, max (b, a + d)).

Greedy can determine what position in the sequence of operation of each point. It is to try to swap adjacent location.

Found: 1 while x <0, y do first large;.

   2. While x> = 0, do first small yx;

   3.x <0 prior to x> = 0

With a heap maintenance, each looking for the highest priority. If you do this point of time, his father did not do, and his father put it merged into the heap, the father done to do it. + May be disjoint-set list maintenance operations inside a whole sequence.

Note that x, y Yaoan separate the same area id; bucket are separated DETAILED x <0 and y, the same id Yaoan x. Otherwise, delete the heap does not work.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define ls Ls[cr]
#define rs Rs[cr]
using namespace std;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
ll Mx(ll a,ll b){return a>b?a:b;}
ll Mn(ll a,ll b){return a<b?a:b;}
const int N=2e5+5;
int n,yf[N],w[N],fa[N],p[N],dy[N],tot; bool vis[N];
int hd[N],mn[N],xnt,to[N<<1],nxt[N<<1],tp[N],tt; ll ans[N];
int pr[N],nt[N],st[N],en[N];
struct Node{
  ll x,y; int id;
  Node(ll x=0,ll y=0,int i=0):x(x),y(y),id(i) {}
  Node operator+ (const Node &b)const
  {return Node(x+b.x,Mx(y,x+b.y),id);}
  bool operator< (const Node &b)const
  {
    if(x<0&&b.x>=0)return false; if(x>=0&&b.x<0)return true;
    if(x<0&&b.x<0)
      {
    if(y!=b.y)return y>b.y;
    if(id!=b.id)return id<b.id;
    return x<b.x;
      }
    if(y-x!=b.y-b.x)return y-x<b.y-b.x;
    if(id!=b.id)return id<b.id;
    return x<b.x;
  }
  bool operator== (const Node &b)const
  { return x==b.x&&y==b.y&&id==b.id;}
}a[N],ya[N];
priority_queue<Node> q,dq;
namespace T{
  const int M=N*20;
  int tot,rt[N],Ls[M],Rs[M]; Node vl[M];
  int nwnd(int pr=0)
  {
    int cr=++tot; ls=Ls[pr]; rs=Rs[pr];
    vl[cr]=vl[pr]; return cr;
  }
  void build(int l,int r,int &cr,int ps)
  {
    cr=nwnd(); if(l==r){vl[cr]=ya[p[l]];return;}
    int mid=l+r>>1;
    if(ps<=mid)build(l,mid,ls,ps);
    else build(mid+1,r,rs,ps);
    vl[cr]=vl[ls]+vl[rs];
  }
  void mrg(int l,int r,int &cr,int pr)
  {
    if(!pr)return; if(!cr){cr=pr;return;}//use is ok
    if(l==r){vl[cr]=vl[cr]+vl[pr];return;}
    int mid=l+r>>1;
    mrg(l,mid,ls,Ls[pr]); mrg(mid+1,r,rs,Rs[pr]);
    vl[cr]=vl[ls]+vl[rs];
  }
  void dfs(int cr)
  {
    build(1,n,rt[cr],dy[cr]);
    for(int i=hd[cr],v;i;i=nxt[i])
      {
    dfs(v=to[i]);
    mrg(1,n,rt[cr],rt[v]);
      }
    ans[cr]=w[cr]+vl[rt[cr]].y;
  }
}
void add(int x,int y)
{to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void frs()
{
  while(dq.size()&&dq.top()==q.top())
      q.pop(), dq.pop();
}
int fnd(int a){ return fa[a]==a?a:fa[a]=fnd(fa[a]);}
void mrg(int x,int y)
{
  if(fa[y]==x)exit(0);
  pr[st[y]]=en[x]; nt[en[x]]=st[y]; en[x]=en[y];
  dq.push(a[x]); a[x]=a[x]+a[y]; q.push(a[x]);
  fa[y]=x; mn[x]=Mn(mn[x],mn[y]);
}
void solve(int x)
{
  int cr=st[x];
  while(cr)
    {
      p[++tot]=cr;dy[cr]=tot;vis[cr]=1;cr=nt[cr];
    }
}
int main()
{
  int op=rdn(); n=rdn();
  for(int i=2;i<=n;i++)yf[i]=rdn(),add(yf[i],i);
  for(int i=1;i<=n;i++)w[i]=rdn();
  for(int i=n;i;i--)
    {
      a[i].x=a[i].y-w[i]; a[yf[i]].y+=w[i];
      a[i].id=i; fa[i]=i; mn[i]=i;
      q.push(a[i]); ya[i]=a[i]; st[i]=en[i]=i;
    }
  vis[0]=1;
  while(q.size())
    {
      frs(); if(!q.size())break;
      Node k=q.top(); q.pop(); int x=k.id;
      if(vis[yf[mn[x]]]){solve(x);continue;}
      mrg(fnd(yf[mn[x]]),x);
    }
  /*for(int i=1;i<=tot;i++)printf("%d ",p[i]);puts("");
    for(int i=1;i<=tot;i++)printf("%d ",dy[i]);puts("");*/
  T::dfs(1);
  for(int i=1;i<=n;i++)printf("%lld ",ans[i]);
  puts(""); return 0;
}

 

Guess you like

Origin www.cnblogs.com/Narh/p/10992539.html