[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 从小到大将点排序。用 F[i] 表示前 i 个点的最大团大小。

那么 F[i] = max(F[k]) + 1      (k < i && (Xi - Wi >= Xk + Wk))

这个前缀最大值查询用线段树实现,然后求出的 F[i] 也要存入线段树的 Xi + Wi 处。

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int MaxN = 200000 + 5, MaxNode = 200000 * 32 + 15, INF = 1000000000;

int n, Index, Root, Ans;
int T[MaxNode], Son[MaxNode][2];

struct ES
{
	int x, w;
	bool operator < (const ES b) const
	{
		return x < b.x;
	}
} E[MaxN];

inline int gmax(int a, int b) {return a > b ? a : b;}

void Set_Max(int &x, int s, int t, int Pos, int Num)
{
	if (x == 0) x = ++Index;
	T[x] = gmax(T[x], Num);
	if (s == t) return;
	int m = (s + t) >> 1;
	if (Pos <= m) Set_Max(Son[x][0], s, m, Pos, Num);
	else Set_Max(Son[x][1], m + 1, t, Pos, Num);
}

int Get_Max(int x, int s, int t, int r)
{
	if (r >= t) return T[x];
	int m = (s + t) >> 1;
	int ret;
	ret = Get_Max(Son[x][0], s, m, r);
	if (r >= m + 1) ret = gmax(ret, Get_Max(Son[x][1], m + 1, t, r));
	return ret;
}

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i)
		scanf("%d%d", &E[i].x, &E[i].w);
	sort(E + 1, E + n + 1);
	Ans = 0;
	Index = 0;
	int t, Fi;
	for (int i = 1; i <= n; ++i)
	{
		t = E[i].x - E[i].w;
		if (i != 1) Fi = Get_Max(Root, -INF, INF, t) + 1;
		else Fi = 1;
		if (Fi > Ans) Ans = Fi;
		t = E[i].x + E[i].w;
		Set_Max(Root, -INF, INF, t, Fi);
	}
	printf("%d\n", Ans);
	return 0;
}

  

时间: 2024-10-05 07:59:40

[Codeforces Round #296 div2 D] Clique Problem 【线段树+DP】的相关文章

Codeforces Round #603 (Div. 2) E. Editor 线段树

E. Editor The development of a text editor is a hard problem. You need to implement an extra module for brackets coloring in text. Your editor consists of a line with infinite length and cursor, which points to the current character. Please note that

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Codeforces Round #401 (Div. 2) E 贪心,线段树

Codeforces Round #401 (Div. 2) A 循环节 B 暴力排一下 C 标记出来,但10^5,特耿直地码了个O(n^2)的上去,最气的是在最后3分钟的时候被叉== D 从后往前贪心暴糙一下就好.比赛时一眼瞄出来了不敢写,搞不懂这样竟然不会超时.. E. Hanoi Factory 题意:n个环体,内径a[i],外径b[i],高h[i].当 a[i+1]<b[i]<=b[i+1] 时,第 i 个环体可以堆在第 i+1个环体上.求可以堆出的最高高度. tags:佩服那些大佬,

Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)

题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n  n个数,然后求有多少个区间[l,r] 满足    a[l]+a[r]=max([l,r]) 思路:首先我们去枚举区间肯定不现实,我们只能取把能用的区间去用,我们可以想下每个数当最大值的时候所做的贡献 我们既然要保证这个数为区间里的最大值,我们就要从两边扩展,找到左右边界能扩展在哪里,这里你直接去枚举肯定不行 这里我们使用了线段树二分去枚举左右区间最远能走到哪里,然后很暴力的去枚举短

Educational Codeforces Round 37-F.SUM and REPLACE (线段树,线性筛,收敛函数)

F. SUM and REPLACE time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard output Let D(x) be the number of positive divisors of a positive integer x. For example, D(2)?=?2 (2 is divisible by 1 and 2), D(6)?

Codeforces #504(div1+div2) 1023D Array Restoration(线段树)

题目大意:给你一个数组,数组是经过q次区间覆盖后的结果,第i次覆盖是把区间内的值赋值为i,其中有若干个地方数值未知(就是0),让你判断这个数组是否可以经过覆盖后得到的,如果可以,输出任意一种可行数组. 思路:不合法的情况只有2种.1:两个相同的数字中间出现了比它小的数字,比如: 6 5 6 就不合法,因为覆盖6的时候是覆盖连续的一段区间,而5比6先覆盖,所以这种情况不存在.我赛后看AC代码的时候发现有的人只是判断是否出现谷形的情况,这种是不对的. 比如这种样例:3 3 3 1 2 这种判断方法会

Codeforces 750E New Year and Old Subsequence 线段树 + dp (看题解)

New Year and Old Subsequence 第一感觉是离线之后分治求dp, 但是感觉如果要把左边的dp值和右边的dp值合起来, 感觉很麻烦而且时间复杂度不怎么对.. 然后就gun取看题解了, 用线段树维护dp的值, 然后区间合并求答案. 每个节点保存dp[ i ][ j ]表示, 把当前管理的区间删到 s{2017}中的 s[ i + 1 ] - s[ j - 1 ],最少删几个, 然后合并的时候5 ^ 3合并. #include<bits/stdc++.h> #define L

codeforces round 533 div2 C Ayoub and Lost Array [dp]

一道思维题 不仅是和这道题在战斗,我和编译器也进行了一场激烈的角逐 因为编译器出了点小问题... 对于dev或者codeblocks 我的方法是卸载了重新装/重启电脑 但是对于vscode 我的方法是, 对着它掉眼泪,看它能不能可怜可怜我,赶紧恢复到正常状态.... #include<bits/stdc++.h> using namespace std; typedef long long ll; //#define int long long const ll N = 2e5 + 1000;

Codeforces Round#320 Div2 解题报告

Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Finding Team Member codeforces 579C A Problem about Polyline codeforces 579D "Or" Game codeforces 579E Weakness and Poorness codeforces 579F LCS Aga