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

POJ 1436 Horizontally Visible Segments 线段树 染色

2013年10月04日 ⁄ 综合 ⁄ 共 808字 ⁄ 字号 评论关闭

题意:两个线段可以相互看见是指两条线段之间没有把他们完全遮住的线段。三角形是指,三条线段,两两之间可以相互看见。

做法:按照横坐标排序,先统计一下在它的范围内可以看见的颜色,然后在把那些它可以看见的区域染上的它自己的颜色。三角形很少,所以这样的算法不会TLE

#include<cstdio>
#include <iostream>
#define LL int
//23123 132131
const int LMT=40;
using namespace std;
LL c[LMT][LMT],num[LMT];
void init(void)
{
    for(int i=0;i<LMT;i++)c[i][0]=c[i][i]=1;
    for(int i=1;i<LMT;i++)
      for(int j=1;j<i;j++)
      c[i][j]=c[i-1][j-1]+c[i-1][j];
}
int leng(LL x)
{
    int ret=0;
    do
        num[ret++]=x&1;
    while(x>>=1);
    return ret;
}
LL work(LL x)
{
    if(x<=1)return 0;
    LL res=0;
    int n1=0,n0=0,len=leng(x);
    for(int i=len-1;i>=0;i--)
    if(num[i])n1++;
    else n0++;
    if(n0>=n1)res++;
    for(int i=1;i<len;i++)
      for(int j=i-1;j>=0&&j>=i-j;j--)
      res+=c[i-1][j];
    n0=0;n1=1;
    for(int i=len-2;i>=0;i--)
    if(num[i])
    {
        for(int j=i;j+n0+1>=n1+i-j;j--)
        res+=c[i][j];
        n1++;
    }
    else n0++;
    return res;
}
int main()
{
    LL n,m;
    init();
    cin>>n>>m;
       cout<<work(m)-work(n-1)<<endl;
    return 0;
}

抱歉!评论已关闭.