zoukankan      html  css  js  c++  java
  • clique 解题报告

    clique

    题目描述

    数轴上有 (n) 个点,第 (i) 个点的坐标为 (x_i),权值为 (w_i)。两个点 (i),(j) 之间存在一条边当且仅当 (abs(x_i-x_j)>=w_i+w_j)。你需要求出这张图的最大团的点数。(团就是两两之间有边的顶点集合)

    输入数据

    第一行一个整数 (n),接下来 (n) 行每行两个整数 (x_i,w_i)

    输出数据

    一行一个整数表示答案

    数据范围

    对于 (20\%) 的数据, (n<=10)
    对于 (60\%) 的数据, (n<=1000)
    对于 (100\%) 的数据, (n<=200000)(0<=|x_i|,w_i<=10^9)


    考试的时候发现了一个性质

    如果三个点按从左到右排,点1点2有边且点2点3右边可以得到点1点3有边

    于是可以(N^2)连边跑topo最长路(从左到右连有向边)

    想拿(set)优化连边但是没想到。

    结果数组开小爆30了。

    正解算是没想到吧。

    如果把点看做形如([x-w,x+w])的区间,那么两个点有连边等价于区间无交点。

    于是问题转化成了不重合的区间数量

    可以简单的贪心,也可以DP

    复杂度都是(O(nlogn))


    Code:

    #include <cstdio>
    #include <algorithm>
    const int N=2e5+10;
    struct node
    {
        int l,r;
        bool friend operator <(node n1,node n2){return n1.r<n2.r;}
    }seg[N];
    int rr[N],dp[N],f[N],pos[N],n;
    int max(int x,int y){return x>y?x:y;}
    int main()
    {
        scanf("%d",&n);
        for(int x,w,i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&w);
            seg[i].l=x-w,seg[i].r=x+w;
            rr[i]=seg[i].r;
        }
        std::sort(seg+1,seg+1+n);
        std::sort(rr+1,rr+1+n);
        rr[0]=seg[1].r-1;
        for(int i=1;i<=n;i++)
        {
            int l=0,r=i-1;
            while(l<r)
            {
                int mid=l+r+1>>1;
                if(seg[i].l>=rr[mid])
                    l=mid;
                else
                    r=mid-1;
            }
            pos[i]=l;
        }
        for(int i=1;i<=n;i++)
            dp[i]=f[pos[i]]+1,f[i]=max(f[i-1],dp[i]);
        printf("%d
    ",f[n]);
        return 0;
    }
    
    

    2018.10.13

  • 相关阅读:
    C# 高效字符串连接 StringBuilder介绍
    C#图解教程
    C#中string类型是值类型还是引用类型?
    UML类图10分钟快速入门
    C#设计模式--单例模式
    计算机是如何启动的?
    2018年计划
    转:SQL进阶之变量、事务、存储过程与触发器
    2020/02/06,武汉
    2020/02/06,渐渐,from eason for you for her
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9784029.html
Copyright © 2011-2022 走看看