CDOJ 1335 郭大侠与“有何贵干?” (线段树&扫描线) - xgtao -

郭大侠与“有何贵干?”

题意

题目给出n(<=100000)个长方体,给的是左下角和右上角的坐标x,y(1<=x,y<=1000000000),z(1<=z<=3),求刚好覆盖k次的体积,答案保证在long long 之内

题解

1.根据数据范围首先要想到要离散化。

2.求覆盖的面积或者体积会想到线段树维护扫描线,求体积难道要用二维线段树?这一道题是可以不的,因为1<=z<=3所以可以把体积拆开当做面积来算,当1<=z<=2就是求前面覆盖K次的面积,当2<=z<=3的时候就是求后面覆盖K次的面积,就是求两次面积。

3.求K次覆盖面积怎么办呢?把扫描线以y的大小从小往大排序,那么每一条扫描从下往上扫的时候,就有会有与上一条扫描线的纵坐标y的差值从而得到高度Δh,怎么得到与上一条扫描线之间覆盖K次的线段的长度呢?在线段树中用tree[k].sum[x]表示这个区间覆盖x次的线段长度,那么与上一条扫描线之间的覆盖k次面积就是Δh*tree[1].sum[K]。

代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000010;
struct Tree{
	int l,r,cover,sum[20];
}tree[N<<3];
#define clr(a,b) memset(a,b,sizeof(a))
int hase[N],cnt,LUcnt,LPcnt,n,K,pre;

struct Line{
	int lx,rx,y,flag;
	bool operator < (const Line& rhs)const{return y < rhs.y;}
	void push(int lx,int rx,int y,int flag){
		this->lx = lx,this->rx = rx,this->y = y,this->flag = flag;
	}
}lineu[N<<2],linep[N<<2];

void build(int k,int l,int r){
	tree[k].sum[0] = hase[r]-hase[l];
	for(int i = 1;i <= 15;++i)tree[k].sum[i] = 0;
	tree[k].l = l,tree[k].r = r,tree[k].cover = 0;
	if(l+1 == r)return;
	int mid = (l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid,r);
}

void processup(int k){
	int l = tree[k].l,r = tree[k].r;
	if(l+1 == r){
		clr(tree[k].sum,0);
		tree[k].sum[min(K+1,tree[k].cover)] = hase[r]-hase[l];
	}
	else{
		clr(tree[k].sum,0);
		for(int i = 0;i <= K+1;++i)
			tree[k].sum[min(K+1,i+tree[k].cover)] = tree[k<<1].sum[i]+tree[k<<1|1].sum[i];
	}
}

void update(int k,int l,int r,int flag){
	if(l == r)return;
	if(tree[k].l >= l && tree[k].r <= r){
		tree[k].cover += flag;
	}
	else{
		int mid = (tree[k].l+tree[k].r)>>1;
		if(r <= mid)update(k<<1,l,r,flag);
		if(l > mid)update(k<<1|1,l,r,flag);
	}
	processup(k);
}

int main(){
	scanf("%d%d",&n,&K);
	for(int i = 1;i <= n;++i){
		int x1,x2,y1,y2,z1,z2;
		scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
		hase[++cnt] = x1,hase[++cnt] = x2;
		if(z1 == 1 && z2 == 2){
			lineu[++LUcnt].push(x1,x2,y1,1);
			lineu[++LUcnt].push(x1,x2,y2,-1);
		}
		if(z1 == 1 && z2 == 3){
			lineu[++LUcnt].push(x1,x2,y1,1);
			lineu[++LUcnt].push(x1,x2,y2,-1);
			linep[++LPcnt].push(x1,x2,y1,1);
			linep[++LPcnt].push(x1,x2,y2,-1);
		}
		if(z1 == 2 && z2 == 3){
			linep[++LPcnt].push(x1,x2,y1,1);
			linep[++LPcnt].push(x1,x2,y2,-1);
		}
	}
	sort(hase+1,hase+1+cnt);
	cnt = unique(hase+1,hase+1+cnt)-hase-1;
	sort(linep+1,linep+1+LPcnt),sort(lineu+1,lineu+1+LUcnt);
	for(int i = 1;i <= LUcnt;++i){
		lineu[i].lx = lower_bound(hase+1,hase+cnt+1,lineu[i].lx)-hase;
		lineu[i].rx = lower_bound(hase+1,hase+cnt+1,lineu[i].rx)-hase;
	}
	for(int i = 1;i <= LPcnt;++i){
		linep[i].lx = lower_bound(hase+1,hase+cnt+1,linep[i].lx)-hase;
		linep[i].rx = lower_bound(hase+1,hase+cnt+1,linep[i].rx)-hase;
	}
	long long res = 0;
	build(1,0,cnt);
	pre = lineu[1].y;
	for(int i = 1;i <= LUcnt;++i){
		res += 1LL*(lineu[i].y-pre)*tree[1].sum[K];
		update(1,lineu[i].lx,lineu[i].rx,lineu[i].flag),pre = lineu[i].y;
	}
	build(1,0,cnt);
	pre = linep[1].y;
	for(int i = 1;i <= LPcnt;++i){
		res += 1LL*(linep[i].y-pre)*tree[1].sum[K];
		update(1,linep[i].lx,linep[i].rx,linep[i].flag),pre = linep[i].y;
	}
	cout<<res<<endl;/**/
	return 0;
}

  

时间: 2024-08-07 17:02:00

CDOJ 1335 郭大侠与“有何贵干?” (线段树&扫描线) - xgtao -的相关文章

cdoj 1334 郭大侠与Rabi-Ribi Label:贪心+数据结构

郭大侠与Rabi-Ribi Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) 最近郭大侠迷上了玩Rabi-Ribi这个游戏. Rabi-Ribi呢,是一个打兔子的动作冒险游戏,萌萌哒的兔子在地上跑来跑去,好萌好萌呀~ 这个游戏是这样玩的,郭大侠作为一个主角,拿着一个小锤子,他的目标是敲晕兔子,然后最后把这些敲晕的兔子都带回家. 当然咯,郭大侠想带回的兔子的总价值最高~ 但是,兔子

cdoj 1334 郭大侠与Rabi-Ribi 贪心+数据结构

郭大侠与Rabi-Ribi Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 最近郭大侠迷上了玩Rabi-Ribi这个游戏. Rabi-Ribi呢,是一个打兔子的动作冒险游戏,萌萌哒的兔子在地上跑来跑去,好萌好萌呀~ 这个游戏是这样玩的,郭大侠作为一个主角,拿着一个小锤子,他的目标是敲晕兔子,然后最后把这些敲晕的兔子都带回家. 当然咯,郭大侠想带回的兔

CDOJ 1338 郭大侠与英雄学院 (并查集) - xgtao -

郭大侠与英雄学院 题意 给出一个矩阵,然后求最小矩阵,最小矩阵就是数字可以变小但是相对大小是不能改变的. 题解 1.分析最基本的思路,假设每个数字都不同,就把记录数字的位置和权值,再把每个数字根据权值从小到大排一次序,这个位置就为max(这一行的最大值,这一列的最大值)+1. 2.但是出现了同一行同一列相同数字怎么办呢?就用并查集把同行同列的相同的数都给用一个id表示出来,再找出每一相同的数各自的每一行每一列综合起来的最大值maxi+1,最后用maxi+1来更新每一相同的数各自的每一行每一列的最

CDOJ 1284 郭大侠与苦恼 (map启发式合并) - xgtao -

题目链接 题目给出一个有N(<=100000)节点的树,找出"好朋友数"的对数,定义好朋友数对于(u,v)如果u->v简单路径上的所有点异或的和为0,那么(u,v)是一对好朋友,但是(u,v)和(v,u)是同一对. 从1号节点搜索下去,用p[v][x]表示从1号节点到达v的异或值为x的出现的个数,节点a到b的路径的的异或值为a^x1^x2^x3^x4..^u...^y1^y2^y3^y4^b,以u为公共祖先val[a] = a^x1^x2^x3^x4..^u,val[b]

郭大侠与Rabi-Ribi (优先队列)

最近郭大侠迷上了玩Rabi-Ribi这个游戏. Rabi-Ribi呢,是一个打兔子的动作冒险游戏,萌萌哒的兔子在地上跑来跑去,好萌好萌呀~ 这个游戏是这样玩的,郭大侠作为一个主角,拿着一个小锤子,他的目标是敲晕兔子,然后最后把这些敲晕的兔子都带回家. 当然咯,郭大侠想带回的兔子的总价值最高~ 但是,兔子实在是太多了,郭大侠的锤子每一秒钟只能敲晕一只兔子,而且每一只兔子只会在地面上逗留a[i]秒,在a[i]秒之后,这一只兔子就会跑回自己的小窝里面. 所以郭大侠面临一些抉择,希望你能帮助他. Inp

hdu1337郭大侠与阴阳家

地址:http://acm.uestc.edu.cn/#/problem/show/1337 思路: 郭大侠与阴阳家 Time Limit: 3000/4000MS (Java/Others)     Memory Limit: 262144/262144KB (Java/Others) Submit Status “污秽”是自异世界“祸野”现身,危害人世的怪物.而“阴阳师”长年以来则与污秽战斗至今. 国中生少年·郭大侠曾以成为能祓除所有污秽的最强阴阳师为目标,但自从遭遇了“雏月之悲剧”后,他便

hdu1342郭大侠与甲铁城

地址:http://acm.uestc.edu.cn/#/problem/show/1342 题目: 郭大侠与甲铁城 Time Limit: 1500/800MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 全世界被产业革命的波澜推动,自近世变迁至近代之时,不死的怪物突然出现.被钢铁的皮膜包覆,只要心脏不被破坏就不会消灭,被它啃咬的人似乎也会在死过一次之后复生,并开始袭击人类.之后被称为卡巴内

hdu1338郭大侠与英雄学院

地址:http://acm.uestc.edu.cn/#/problem/show/1338 思路: 郭大侠与英雄学院 Time Limit: 6000/2000MS (Java/Others)     Memory Limit: 225535/225535KB (Java/Others) Submit Status 大部分的人类,在这个时代里都拥有名为“个性”的力量,但有力量之人却不一定都属於正义的一方.只要邪恶出现的地方,必定会有英雄挺身而出拯救众人.一名天生没有力量的少年——郭大侠从小就憧

hdu1339郭大侠与线上游戏

地址:http://acm.uestc.edu.cn/#/problem/show/1339 题目: 郭大侠与线上游戏 Time Limit: 6000/2000MS (Java/Others)     Memory Limit: 125535/65535KB (Java/Others) Submit Status 曾在网络游戏告白,但对方是假冒女生的人妖,而对此有阴影的郭大侠,坚持把游戏和现实分得清清楚楚.有一天竟被网络游戏中的女玩家告白了,虽然在游戏中接受了亚子的表白而结婚,但仍然不敢确信亚