LightOJ 1089 - Points in Segments (II) 线段树区间修改+离散化

http://www.lightoj.com/volume_showproblem.php?problem=1089

题意:给出许多区间,查询某个点所在的区间个数

思路:线段树,由于给出的是区间,查询的是点,考虑将其离线并离散化,普通线段树即可。

/** @Date    : 2016-12-17-20.49
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version :
  */
#include<bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

struct yuu
{
    int l, r;
    int sum, add;
}tt[N << 4];

void pushdown(int p)
{
	if(tt[p].add != 0)
	{
		tt[p << 1].sum += tt[p].add;
		tt[p << 1 | 1].sum += tt[p].add;
		tt[p << 1].add += tt[p].add;
		tt[p << 1 | 1].add += tt[p].add;
		tt[p].add = 0;
	}
}

void pushup(int p)
{
	tt[p].sum = tt[p << 1].sum + tt[p << 1 | 1].sum;
}

void build(int l, int r, int p)
{
	tt[p].l = l;
	tt[p].r = r;
	tt[p].sum = 0;
	tt[p].add = 0;
	if(l == r)
		return ;
	int mid = (l + r) >> 1;
	build(l, mid, p << 1);
	build(mid + 1, r, p << 1 | 1);
	pushup(p);
}

void updata(int l, int r, int v, int p)
{
	if(l <= tt[p].l && r >= tt[p].r)
    {
		tt[p].sum += v;
		tt[p].add += v;
        return ;
    }
	pushdown(p);
	int mid = (tt[p].l + tt[p].r) >> 1;
	//cout <<mid<< endl;
	if(l <= mid)
		updata(l, r, v, p << 1);
	if(r > mid)
		updata(l, r, v, p << 1 | 1);
	pushup(p);
}

int query(int l, int r, int p)
{
	if(l <= tt[p].l && r >= tt[p].r)
    {
		return tt[p].sum;
    }
    pushdown(p);
	int mid = (tt[p].l + tt[p].r) >> 1;
	int ans = 0;
	if(l <= mid)
		ans += query(l, r, p << 1);
	if(r > mid)
		ans += query(l, r, p << 1 | 1);
	return ans;
}
mapq;
map::iterator it;
int l[N], r[N];
int x[N];
int main()
{

	int T;
	int cnt = 0;
	cin >> T;
	while(T--)
	{
		int n, m;
		q.clear();
		scanf("%d%d", &n, &m);
		for(int i = 0; i < n; i++)
		{
			scanf("%d%d", l + i, r + i);
			q[l[i]] = 1;
			q[r[i]] = 1;
		}
		for(int i = 0; i < m; i++)
		{
			scanf("%d", x + i);
			q[x[i]] = 1;
		}

		printf("Case %d:\n", ++cnt);
		int ct = 0;
		for(it = q.begin(); it != q.end(); it++)
		{
			it->se = ++ct;
		}
		build(0, ct, 1);
		for(int i = 0; i < n; i++)
		{

			//cout << q[l[i]] <<"~"<<q[r[i]]<< endl;
			updata(q[l[i]], q[r[i]], 1, 1);
		}
		for(int i = 0; i < m; i++)
		{
		   // cout << q[x[i]] << endl;
			printf("%d\n", query(q[x[i]], q[x[i]], 1));
		}
	}
    return 0;
}
时间: 2024-08-02 15:14:25

LightOJ 1089 - Points in Segments (II) 线段树区间修改+离散化的相关文章

POJ 1436 Horizontally Visible Segments(线段树区间修改)

题目链接:点击打开链接 题意:n条竖直线段,如果两条线段之间可见(即可以用一条水平线段连接而不触碰其他线段),则称它们可见.   如果三条线段任意两条都可见, 则称它们为a triangle of segments, 求a triangle of segments的个数 思路: 一开始真没想到n^3的复杂度可以过...  如果这样的话, 问题的关键就是怎样判断任意两个线段是否可见. 那么如果对y坐标建立区间, 这就成了线段树的区间覆盖问题. 另外, 由于是用点代替线段, 所以对于"可见"

hiho1079 线段树区间修改离散化

题目链接: hihocoder1079 代码: #include<iostream> #include<cstdio> #include<cstring> #include<set> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 100050 using namespace std; int cnt[ma

POJ 2528 Mayor&#39;s posters(线段树区间染色+离散化或倒序更新)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 59239   Accepted: 17157 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

poj 2777 Count Color(线段树区间修改)

题目链接:http://poj.org/problem?id=2777 题目意思:就是问你在询问的区间里有几种不同的颜色 思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数.这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了.... 代码核心处就在计数那儿

hdu-5023 A Corrupt Mayor&#39;s Performance Art (线段树区间修改)

今天集训队打比赛的一道题,很明显是个线段树,我们队照着lrj蓝书敲了一通,机智的将修改值和加和改成了位运算:|= 但是好像哪里出了点小问题,就是不对,赛后又水了一遍,竟然过了...发现还是lrj的书好啊,市面上的模板一点也不好用,连区间修改都没有 . 等集训完了要静心好好系统的学习一下线段树 . 多看多刷lrj的书 . 细节参见代码: #include<bits/stdc++.h> using namespace std; const int maxn = 1000000 + 5; int n

【线段树区间修改】fzu2105Digits Count

/* 题意: 给出数组A,有以下几个操作: 1: AND(opn, L, R):把区间[L, R]中的元素A[i]改为A[i] & opn;;;;;; 2: OR(opn, L, R) :把区间[L, R]中的元素A[i]改为A[i] | opn;;;;;;; 3: XOR(opn, L, R):把区间[L, R]中的元素A[i]改为A[i] ^ opn;;;;;;; 4: SUM(L, R) :对区间[L, R]中的元素求和:::: ------------------------------

Wikilo 1191线段树区间修改单点查询

这题也算比较容易的了. 如果哪个区间已经没有黑色的话,就不用update了,就是因为这个原因WA了2发,唉-- #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #incl

线段树区间修改模板

本来打算把大白书第三章一口气攻下来的,但是这个线段树也是卡了好久. 不敢过题太快,怕自己走马观花到头来结果什么都不会. 可也不能再拖了,在做题中也许有更多的体会. 模板一:1 L R v 表示区间[L, R]所有元素都加上v2 L R   表示查询区间[L, R]的sum, min, maxsumv[o]的定义为:如果只执行节点o及其子孙节点的中的add操作,节点o对应区间中所有数之和 1 //线段树区间修改 2 //1 L R v 表示区间[L, R]所有元素都加上v 3 //2 L R 表示