Codeforces 528B Clique Problem dp+线段树(or 树状数组)

题目链接:点击打开链接

题意:

给定数轴上的n个点。

下面n行每行两个数 xi, wi 表示点和点权。

对于任意两个点u, v

若dis(u,v) >= u_w+v_w 则这两个点间可以建一条边。(in other words 若两点间距离大于两点的权值和则可以建边)

找一个最大团,输出这个最大团的点数。

其实对于一个权值点我们可以认为是一个区间

如: 4 5 ,可以认为是区间[-1, 9]

则这个点可以从区间(-inf, 1]转移过来,即val(9) = max(val(9), 区间(-inf, -1]最大值+1)

然后前面区间最值就用树状数组或者线段树维护

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <queue>
#include <set>
#include <vector>
#include <string>
#include <algorithm>
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if (x>9) pt(x / 10);
    putchar(x % 10 + '0');
}
using namespace std;
const int N = 400010;
#define L(x) tree[x].l
#define R(x) tree[x].r
#define Max(x) tree[x].max
#define Lson(x) (x<<1)
#define Rson(x) (x<<1|1)
#define Lazy(x) tree[x].lazy
struct Node{
    int l, r, max, lazy;
}tree[N<<2];
void Down(int id){
    Max(Lson(id)) = max(Lazy(id), Max(Lson(id)));
    Max(Rson(id)) = max(Lazy(id), Max(Rson(id)));
    Lazy(Lson(id)) = max(Lazy(id), Lazy(Lson(id)));
    Lazy(Rson(id)) = max(Lazy(id), Lazy(Rson(id)));
}
void U(int id){
    Max(id) = max(Max(Lson(id)), Max(Rson(id)));
}
void build(int l, int r, int id){
    L(id) = l; R(id) = r;
    Max(id) = Lazy(id) = 0;
    if (l == r)return;
    int mid = (l + r) >> 1;
    build(l, mid, Lson(id)); build(mid + 1, r, Rson(id));
}
int query(int l, int r, int id){
    if (l == L(id) && R(id) == r)return Max(id);
    Down(id);
    int mid = (L(id) + R(id)) >> 1, ans ;
    if (r <= mid)
        ans = query(l, r, Lson(id));
    else if (mid < l)
        ans = query(l, r, Rson(id));
    else ans = max(query(l, mid, Lson(id)), query(mid + 1, r, Rson(id)));
    U(id);
    return ans;
}
void up(int l, int r, int val, int id){
    if (l == L(id) && R(id) == r){
        Max(id) = max(Max(id), val);
        Lazy(id) = max(Lazy(id), val);
        return;
    }
    Down(id);
    int mid = (L(id) + R(id)) >> 1;
    if (r <= mid)
        up(l, r, val, Lson(id));
    else if (mid < l)
        up(l, r, val, Rson(id));
    else {
        up(l, mid, val, Lson(id));
        up(mid + 1, r, val, Rson(id));
    }
    U(id);
}
vector<int>G;
int hehehe;
struct Edge{
    int l, r;
}x[N];
bool cmp(Edge a, Edge b){
    return a.r < b.r;
}
int n, m;
int a[N], b[N];
int main(){
    while (~scanf("%d", &n)){
        G.clear();
        for (int i = 1; i <= n; i++){
            rd(a[i]); rd(b[i]);
            x[i].l = a[i] - b[i];
            x[i].r = a[i] + b[i];
            G.push_back(x[i].l);
            G.push_back(x[i].r);
        }
        sort(G.begin(), G.end());
        G.erase(unique(G.begin(), G.end()), G.end());
        for (int i = 1; i <= n; i++){
            x[i].l = lower_bound(G.begin(), G.end(), x[i].l) - G.begin() + 1;
            x[i].r = lower_bound(G.begin(), G.end(), x[i].r) - G.begin() + 1;
        }
        sort(x + 1, x + n + 1, cmp);
        build(1, G.size(), 1);
        int ans = 1;
        for (int i = 1; i <= n; i++){
            int tmp = query(1, x[i].l, 1) + 1;
            ans = max(ans, tmp);
            up(x[i].r, x[i].r, tmp, 1);
        }
        pt(ans); puts("");
    }
    return 0;
}
时间: 2024-10-16 22:10:16

Codeforces 528B Clique Problem dp+线段树(or 树状数组)的相关文章

分析公式 Codeforces 528B Clique Problem

http://codeforces.com/contest/528/problem/b Clique Problem time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The clique problem is one of the most well-known NP-complete problems. Under some

codeforces 706C Hard problem DP(动态规划)问题

题目链接:http://codeforces.com/problemset/problem/706/C 题目大意:  给定n个字符串, 每个字符串可以颠倒前后位置(第一个字母到最后一个,第二个字母到倒数第二位) 每次颠倒需要花费ci的力气, 要求将所给的n个字符串用最小力气按字典序排列, 输出力气值, 如果无法按字典序排列, 则输出-1 数据范围:2?≤?n?≤?100?000 . ci (0?≤?ci?≤?1e9) 所有字符串总长度不会超过1000000. 解题思路: 这是一道DP题, dp[

Codeforces 527D Clique Problem

题意:给你一个xi,wi的点集合 ,问你其中最大的子集满足|xi - xj| >= wi + wj 的大小是多少. 解题思路:dp+离散化+树状数组.把它看成是 一条边[xi-wi,xi+wi] 去覆盖区域就行了 解题代码: 1 // File Name: d.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月18日 星期三 15时28分50秒 4 5 #include<vector> 6 #include<list>

[Codeforces Round #296 div2 D] Clique Problem 【线段树+DP】

题目链接:CF - R296 - d2 - D 题目大意 一个特殊的图,一些数轴上的点,每个点有一个坐标 X,有一个权值 W,两点 (i, j) 之间有边当且仅当 |Xi - Xj| >= Wi + Wj. 求这个图的最大团. 图的点数 n <= 10^5. 题目分析 两点之间右边满足 Xj - Xi >= Wi + Wj (Xi < Xj)       ==>     Xj  - Wj >= Xi + Wi (Xi < Xj) 按照坐标 x 从小到大将点排序.用

Codeforces 597C. Subsequences (树状数组+dp)

题目链接:http://codeforces.com/contest/597/problem/C 给你n和数(1~n各不同),问你长为k+1的上升自序列有多少. dp[i][j] 表示末尾数字为i 长度为j的上升子序列个数,但是dp数组是在树状数组的update函数中进行更新. update(i, val, j)函数表示在i的位置加上val,更新dp[i][j]. sum(i, j)就是求出末尾数字小于等于i 且长度为j的子序列有多少个. 1 //#pragma comment(linker,

题解 HDU 3698 Let the light guide us Dp + 线段树优化

http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 62768/32768 K (Java/Others) Total Submission(s): 759    Accepted Submission(s): 253 Problem Description Plain of despair was

Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组

Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other. The boys decided to h

Codeforces 486E LIS of Sequence(线段树+LIS)

题目链接:Codeforces 486E LIS of Sequence 题目大意:给定一个数组,现在要确定每个位置上的数属于哪一种类型. 解题思路:先求出每个位置选的情况下的最长LIS,因为开始的想法,所以求LIS直接用线段树写了,没有改,可以用 log(n)的算法直接求也是可以的.然后在从后向前做一次类似LIS,每次判断A[i]是否小于f[dp[i]+1],这样就可以确定该位 置是否属于LIS序列.然后为第三类的则说明dp[i] = k的只有一个满足. #include <cstdio>

CodeForces 600E Lomsat gelral(线段树合并)

题目链接:http://codeforces.com/problemset/problem/600/E You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour. Let's call colour c dominating in the subtree of vertex v if there are no other colours that appear in the