1003 线段树树状数组区间覆盖

算法:

比赛时是对线段长度从大到小排序,一次插入查询。一直WA。

赛后证明这种算法是错误的。

比如1 6 5 7 6 10这组数据就无法通过。

正确的算法应该是对线段的x从小到大排序,Y从大到小排序。

用线段树或树状数组维护区间和都可。

View Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<map>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

struct node
{
  int left, right;
  int num;
  int lazy;
}seg[4000010];

int N, M;

struct flower
{
  int a,b, c;
  bool operator < (const flower &A) const
  {
    // if ( abs(A.b - A.a) != abs(b - a) )
      //  return abs(A.b - A.a) < abs(b-a);
     if( a != A.a )
        return a < A.a;
     else
        return b > A.b;
  }
}p[201000];

int v[400010];
int an[400010];

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

void update(int x)
{
   seg[x * 2].lazy += seg[x].lazy;
   seg[x * 2].num +=  seg[x].lazy;
   seg[x * 2 + 1].lazy += seg[x].lazy;
   seg[x * 2 + 1].num += 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].num +=  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);    
  }    
}

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

int main( )
{ 
  int cnt;
  while( scanf("%d",&N) != EOF )
  {  
     cnt = 0;
     for( int i = 1; i <= N; i++)
     {
        scanf("%d%d",&p[i].a,&p[i].b);
        p[i].c = i;
        v[cnt++] = p[i].a;
        v[cnt++] = p[i].b;      
     }
     sort(v, v + cnt);
     sort(p + 1, p + N + 1);
     cnt = unique(v, v + cnt) - v ;
     build(0,cnt,1);
     for( int i = 1; i <= N; i++)
          an[i] = 0;
     for( int i = 1; i <= N; i++)
     {  
        if( i != 1 && p[i].a == p[i-1].a && p[i].b == p[i-1].b )
        {
            an[p[i].c] = an[p[i-1].c];
            int x = lower_bound(v, v + cnt, p[i].a) - v; 
            int y = lower_bound(v, v + cnt, p[i].b) - v; 
            add(1, x, y, 1);
            continue;
        }
        int x = lower_bound(v, v + cnt, p[i].a) - v; 
        int y = lower_bound(v, v + cnt, p[i].b) - v;
        an[p[i].c] = sum(1, x, y);
        add(1, x, y, 1);
   
     }
     printf("%d",an[1]);
     for( int i = 2; i <= N; i++)
     {  
         printf(" %d",an[i]);
     }
     puts("");
  }
  return 0;  
}

posted on 2012-08-16 19:21  more think, more gains  阅读(316)  评论(0编辑  收藏  举报

导航