sgu128:Snake

这道题是看04年《线段树的应用》才会的...

各种WA就是因为打错一个字母555555

代码能力有待提升...

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int MAXN = 10005;
const int base = 10000;

int N;
struct Point
{
  int x, y;	
  int num;
}v[MAXN], tmp, src[MAXN];

int nextx[MAXN] = {0}, nexty[MAXN] = {0};

int ans = 0;

struct seg
{
  int l, r;
  int sum;	
}tree[base<<3] = {0};

bool cmpx(const Point &A, const Point &B)
{
  if(A.x != B.x) return A.x < B.x;
  else return A.y < B.y;	
}

bool cmpy(const Point &A, const Point &B)
{
  if(A.y != B.y) return A.y < B.y;
  else return A.x < B.x;	
}

bool check()
{
  bool used[MAXN] = {false};
  for(int i = 1, pd = 1; !used[i];)
  {
    used[i] = true;
	if(pd) i = nextx[i];
	else i = nexty[i];
	pd ^= 1; 
  }
  for(int i = 1; i <= N; ++i)
    if(!used[i]) return false;
  return true; 
}

void insert(int x, int num)
{
  int mid = (tree[num].l+tree[num].r)>>1;
  tree[num].sum++;
  if(tree[num].l == tree[num].r) return;
  if(x <= mid) insert(x, num<<1);
  else insert(x, (num<<1)+1);
}

void cancel(int x, int num)
{
  int mid = (tree[num].l+tree[num].r)>>1;
  tree[num].sum--;
  if(tree[num].l == tree[num].r) return;
  if(x <= mid) cancel(x, num<<1);
  else cancel(x, (num<<1)+1);
}

int search(int d, int u, int num)
{
  int l = tree[num].l, r = tree[num].r;
  int mid = (l+r)>>1;
  if(l == d && r == u) return tree[num].sum;
  if(u <= mid) return search(d, u, num<<1);
  else if(d > mid) return search(d, u, (num<<1)+1);
  else return search(d, mid, num<<1)+search(mid+1, u, (num<<1)+1);	
}

void work()
{
<pre name="code" class="cpp">  bool hash[MAXN] = {0};

 
  for(int i = 1; i <= N; ++i)
  {
    hash[v[i].num] = true;
	if(!hash[nextx[v[i].num]]) insert(v[i].y, 1);
    else cancel(v[i].y, 1);
    if(!hash[nexty[v[i].num]] && src[v[i].num].y <= src[nexty[v[i].num]].y-2 && search(src[v[i].num].y+1, src[nexty[v[i].num]].y-1, 1) > 0)
    {
      printf("0");
	  return;	
    }
  }
  printf("%d", ans);
}

void make(int l, int r, int num)
{
  int mid = (l+r)>>1;
  tree[num].l = l, tree[num].r = r;
  if(l == r) return;
  make(l, mid, num<<1);	
  make(mid+1, r, (num<<1)+1);	
} 

int main()
{
  make(0, base<<1, 1);
  scanf("%d", &N);
  for(int i = 1; i <= N; ++i)
  {
    scanf("%d%d", &v[i].x, &v[i].y);
    v[i].x += base, v[i].y += base;
    v[i].num = i; 
    src[i] = v[i];
  }
  sort(v+1, v+N+1, cmpy);
  for(int i = 1; i < N;)
    if(v[i].y == v[i+1].y)
    {
      nextx[v[i].num] = v[i+1].num;
      nextx[v[i+1].num] = v[i].num;
      ans += v[i+1].x-v[i].x;
	  i += 2;	
    }
    else 
    {
      printf("0");
	  return 0;	
    }
  sort(v+1, v+N+1, cmpx);
  for(int i = 1; i < N;)
    if(v[i].x == v[i+1].x)
    {
      nexty[v[i].num] = v[i+1].num;
      nexty[v[i+1].num] = v[i].num;
      ans += v[i+1].y-v[i].y;
	  i += 2;	
    }
    else 
    {
      printf("0");
	  return 0;	
    }
  if(!check())
  {
  	printf("0");
	return 0;	
  }  
  work();
  return 0;	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值