现在的位置: 首页 > 综合 > 正文

Problem B. Money out of Thin Air

2013年06月15日 ⁄ 综合 ⁄ 共 2391字 ⁄ 字号 评论关闭

算法

1.先用DFS把员工之间关系系列找出,使之连续,转换为对线段进行操作,用L【】记录左边界,R【】记录右边界。

2.线段树,单点更新,区间更新,lazy延时标记。

View Code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
#define MAXN 51000
#define LL long long
struct node
{
  int left, right;
  LL salary;
  LL lazy;
}seg[500010];

int N, M;
int salary[MAXN], visit[MAXN];  
int L[MAXN], R[MAXN], dfn[MAXN];
int que[MAXN];

vector<int>p[51100];

void build(int l, int r, int root)
{
   int mid = (l + r) / 2;
   seg[root].left = l;
   seg[root].right = r;
   seg[root].lazy = 0;
   if( l == r )
   {
      seg[root].salary = salary[dfn[l]];
      return;
   }
   build(l,mid,root*2);
   build(mid+1,r,root*2+1);
   seg[root].salary = seg[root*2].salary + seg[root * 2 + 1].salary;
}

void update(int x)
{
   seg[x * 2].lazy += seg[x].lazy;
   seg[x * 2].salary += (LL) (seg[x * 2].right - seg[x * 2].left + 1 ) * seg[x].lazy;
   seg[x * 2 + 1].lazy += seg[x].lazy;
   seg[x * 2 + 1].salary += (LL) (seg[x * 2 + 1].right - seg[x * 2 + 1].left + 1 ) * seg[x].lazy;
   seg[x].lazy = 0;
}

void add( int root, int u, int v, int val)
{
  int mid = (seg[root].left + seg[root].right) / 2;
  if(  seg[root].left == u && v == seg[root].right )
  {
      seg[root].lazy += val;
      seg[root].salary += (LL) (v - u + 1) * val; 
      return;
  }  
  if( seg[root].lazy != 0 )
     update( root ); 
  if( u > mid )
       add( root * 2 + 1, u, v, val);
  else if( v <= mid )
       add( root * 2, u, v, val);
  else
  { 
      add( root * 2, u, mid, val);
      add( root * 2 + 1, mid + 1, v,val);    
  }    
   seg[root].salary = seg[root*2].salary + seg[root * 2 + 1].salary;
}

LL sum( int root,int u, int v)
{
  int mid = (seg[root].left + seg[root].right) / 2;
  if(  seg[root].left == u && v == seg[root].right )
  {
     return seg[root].salary;     
  }  
  if( seg[root].lazy != 0 )
      update(root);
  LL st = 0;
  if( u > mid )
      return sum( root * 2 + 1, u, v);
  else if( v <= mid )
      st += sum( root * 2, u, v);
  else
  { 
      st += sum( root * 2, u, mid);
      st += sum( root * 2 + 1, mid + 1, v);    
  }    
  return st;  
}


int main( )
{
  int pid, x, f, id, a, b, c, fuck = 0;
  char str[100];
  while( scanf("%d%d%d",&N,&M,&salary[0]), N|M|salary[0])
  {
    for( int i = 0; i <= N; i++)
         p[i].clear();
    for( int i = 1; i < N; i++)
    {
       scanf("%d%d",&a,&salary[i]);
       p[a].push_back(i);
    }
    memset(visit,0,sizeof(visit));
    memset(L, 0, sizeof(L));
    memset(R, 0, sizeof(R));
    pid = 0;
    id = 0;
    que[pid] = 0;
    dfn[id] = 0;
    while( pid >= 0 )
    {
       int u = que[pid];
       if( !visit[u] )
       {
           dfn[id] = u;
           L[u] = id;
           visit[u] = 1;
           id++;
       }
       int n = p[u].size();
       f = 0;
       for( x = 0; x < n; x++)
       {
           if( !visit[p[u][x]] )
           {
              que[++pid] = p[u][x]; //进栈 
              f = 1;           
              //break; 没去掉这个一直TLE,速度太慢,一次入栈就可以了 
           }          
       }
       if( f ) continue;
       if( x == n )
       { 
          R[u] = id - 1;
          --pid;    //退栈
       }            
    }
    build(0,N-1,1);
    for( int i = 1; i <= M; i++)
    {
      scanf("%s%d%d%d",str,&a,&b,&c);
      if( str[0] == 'e' )
      {
          LL x = sum(1,L[a],L[a]);
          if( x < b )
             add(1,L[a],L[a],c);    
          
      }
      else
      {  
          LL x = sum(1,L[a],R[a]);
          if( x < (LL) (R[a] - L[a] + 1 ) * b )
            add(1, L[a],R[a],c);
          
      }
    }
    if( fuck )
        puts("");
    fuck = 1;
    for( int i = 0; i < N; i++)
    {
        printf("%lld\n",sum(1,L[i],L[i]));   
    }           
         
  } 
  return 0;  
}

抱歉!评论已关闭.