hdu 4553 约会安排 (两个线段树维护区间)

include

include

include

include

include

include

include

include

define ll long long

define FOR(i,l,r) for(int i = l ; i <= r ;++i )

define inf 1<<30

define EPS (1e-9)

define lson(p) (p<<1)

define rson(p) (p<<1|1)

using namespace std;
typedef pair<int,int> pii;
const int N = 1e5+30;
int n,m;
struct node{
int l,r;
int lsum,rsum,ssum;
}a[N<<2],b[N<<2];

void push_up(int rt,int l,int r){
int mid = (l+r)>>1;
a[rt].lsum = a[lson(rt)].lsum; // 左子树的左连续空间更新父亲
a[rt].rsum = a[rson(rt)].rsum; // 右子树的右连续空间更新父亲
// 总连续空间为 max(左子树总连续,右子树总连续, 左子树右连续+右子树左连续)
a[rt].ssum = max(max(a[lson(rt)].ssum,a[rson(rt)].ssum),a[lson(rt)].rsum+a[rson(rt)].lsum);
if(a[lson(rt)].lsum == mid-l+1) a[rt].lsum += a[rson(rt)].lsum; // 左子树左连续包含了整个左子树,则父亲的左连续扩充右子树的左连续
if(a[rson(rt)].rsum == r-mid) a[rt].rsum += a[lson(rt)].rsum;
b[rt].lsum = b[lson(rt)].lsum;
b[rt].rsum = b[rson(rt)].rsum;
b[rt].ssum = max(max(b[lson(rt)].ssum,b[rson(rt)].ssum),b[lson(rt)].rsum+b[rson(rt)].lsum);
if(b[lson(rt)].lsum == mid-l+1) b[rt].lsum += b[rson(rt)].lsum;
if(b[rson(rt)].rsum == r-mid) b[rt].rsum += b[lson(rt)].rsum;

}

void push_down(int rt,int l,int r){
int mid = (l+r)>>1;
if(a[rt].ssum == r-l+1){ // 父亲被覆盖 ,子区间也被覆盖
a[lson(rt)].lsum = a[lson(rt)].rsum = a[lson(rt)].ssum = mid-l+1;
a[rson(rt)].lsum = a[rson(rt)].rsum = a[rson(rt)].ssum = r-mid;
}else if(a[rt].ssum == 0){ // 父亲被情空,子区间清空
a[lson(rt)].lsum = a[lson(rt)].rsum = a[lson(rt)].ssum = 0;
a[rson(rt)].lsum = a[rson(rt)].rsum = a[rson(rt)].ssum = 0;
}
if(b[rt].ssum == r-l+1){
b[lson(rt)].lsum = b[lson(rt)].rsum = b[lson(rt)].ssum = mid-l+1;
b[rson(rt)].lsum = b[rson(rt)].rsum = b[rson(rt)].ssum = r-mid;
}else if(b[rt].ssum == 0){
b[lson(rt)].lsum = b[lson(rt)].rsum = b[lson(rt)].ssum = 0;
b[rson(rt)].lsum = b[rson(rt)].rsum = b[rson(rt)].ssum = 0;
}
}

void build(int r,int le,int re){
a[r].lsum = b[r].lsum = (re-le+1);
a[r].rsum = b[r].rsum = (re-le+1);
a[r].ssum = b[r].ssum = (re-le+1);
a[r].l = le,a[r].r = re;
b[r].l = le,b[r].r = re;
if(le==re) return ;
int mid = (le+re)>>1;
build(lson(r),le,mid);
build(rson(r),mid+1,re);
}

void update(int op,int l,int r,int rt){
if(a[rt].l>=l && a[rt].r <=r){
if(op==1){ // ds更新自己
a[rt].lsum = a[rt].rsum = a[rt].ssum = 0;
}else if(op==0){ // ns更新两棵树
a[rt].lsum = a[rt].rsum = a[rt].ssum = 0;
b[rt].lsum = b[rt].rsum = b[rt].ssum = 0;
}else{ // 两棵树清空
a[rt].lsum = a[rt].rsum = a[rt].ssum = a[rt].r-a[rt].l +1;
b[rt].lsum = b[rt].rsum = b[rt].ssum = b[rt].r-b[rt].l +1;
}
return ;
}
int mid = (a[rt].l + a[rt].r)>>1;
push_down(rt,a[rt].l,a[rt].r); // 下方标记
if(l<=mid) update(op,l,r,lson(rt));
if(r>mid) update(op,l,r,rson(rt));
push_up(rt,a[rt].l,a[rt].r); // 上提标记
}

int query(int op,int rt,int len){
if(a[rt].l==a[rt].r) return a[rt].l;
push_down(rt,a[rt].l,a[rt].r);
int mid = (a[rt].l + a[rt].r) >> 1;
if(op){ // ds
if(a[lson(rt)].ssum>=len)
return query(op,lson(rt),len);
else if(a[lson(rt)].rsum + a[rson(rt)].lsum >=len) // 左子树的右区间加右子树的左区间满足
return mid-a[lson(rt)].rsum +1; // 起点一定在左子树
else
return query(op,rson(rt),len);
}else{ // ns
if(b[lson(rt)].ssum>= len)
return query(op,lson(rt),len);
else if(b[lson(rt)].rsum + b[rson(rt)].lsum >=len)
return mid-b[lson(rt)].rsum +1;
else
return query(op,rson(rt),len);
}
}
char op[20];
void solve(int cas){
printf("Case %d:\n",cas);
scanf("%d%d",&n,&m);
build(1,1,n);
int l,r;
FOR(i,1,m){
scanf("%s%d",op,&l);
if(op[0]==‘D‘){
if(a[1].ssum>=l){
int pos = query(1,1,l);
printf("%d,let‘s fly\n",pos);
update(1,pos,pos+l-1,1);
}else{
puts("fly with yourself");
}
}else if(op[0]==‘N‘){
if(a[1].ssum>=l){
int pos = query(1,1,l);
printf("%d,don‘t put my gezi\n",pos);
update(0,pos,pos+l-1,1);
}else if(b[1].ssum>=l){
int pos = query(0,1,l);
printf("%d,don‘t put my gezi\n",pos);
update(0,pos,pos+l-1,1);
}else{
puts("wait for me");
}
}else{
scanf("%d",&r);
update(2,l,r,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
int main(){
int t;
scanf("%d",&t);
for(int i=1;i<=t;++i){
solve(i);
}
return 0;
}

原文地址:https://www.cnblogs.com/xxrlz/p/11359693.html

时间: 2024-08-07 23:16:11

hdu 4553 约会安排 (两个线段树维护区间)的相关文章

HDU 4553 约会安排(二维线段树)

Problem Description 寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复"呵呵",所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事. 我们已知小明一共有T的空闲时间,期间会有很多女神或者基友来找小明. 作为一个操作系统曾经怒考71分的大神,小明想到了一个算法,即"首次适应算法",根据操作系统课本的描述,就是找一段最

hdu 1556:Color the ball(线段树,区间更新,经典题)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7941    Accepted Submission(s): 4070 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电

hdu 1698:Just a Hook(线段树,区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 15129    Accepted Submission(s): 7506 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing f

线段树维护区间最大子段和 枚举 HDU6638

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6638 题意:在一个二维坐标系上给你n(n<=2000)个点,点带有一个价值w(有正有负),点的坐标都在(-1e9,1e9)的范围之间,可任意用一个平行于坐标轴的矩形框住一片区域,求这片区域框住的点的价值和 分析:点的坐标范围太大,离散化应能想到.离散化后可以考虑枚举左边界,枚举左边界后按照横坐标的依次加点(以一列一列为单位),用线段树维护一列的最大子段和,每移动到新的一列,继续加点时,等价于向原先的

线段树维护区间最大子段和

线段树:我还是很强的 简略讲解 要用线段树维护区间,我们要明确: 线段树存什么东西 怎么合并 如果有区间修改,怎么打标记 对于区间最大子段和,我们可以记录四个值:以维护的区间左端点为起点的最大子段和,以维护的区间右端点为终点的最大子段和,在维护区间内的最大子段和 和维护区间所有元素的和 合并的话稍微麻烦一些,看代码吧: inline void up(int p){ tree[p].sum=tree[ls].sum+tree[rs].sum; //维护区间总和 tree[p].ll=max(tre

最敏捷的机器人(线段树维护区间最值)

题面: Wind设计了很多机器人.但是它们都认为自己是最强的,于是,一场比赛开始了--机器人们都想知道谁是最敏捷的,于是它们进行了如下一个比赛.首先,他们面前会有一排共n个数,它们比赛看谁能最先把每连续k个数中最大和最小值写下来,当然,这些机器人运算速度都很,它们比赛的是谁写得快.但是Wind也想知道答案,你能帮助他吗? Input: 每组测试数据 第1行为n,k(1<=k<=n<=100000) 第2行共n个数,为数字序列,所有数字均在int范围内. Output: 共n-k+1行 第

线段树维护区间开方/除法

今天考试考了一些神仙数据结构 T1 线段树维护区间加,区间开方,区间和 (数据范围:5e5) T2 线段树维护区间加,区间除,区间和,区间最值 对于这些题目,就像是之前考的区间与,区间或一样,除法,开方的操作会让各个数字之间越来越相近,最后变成一串一串连续的数字都是一样的,所以对于这一部分的操作我们一定程度上使用暴力,而如果一段都相等就相当于直接进行区间剪发的操作 那么我们来看如何判断区间一段都相等,那我们只需要维护区间的最值,最小值==最大值就完全相等了 然后.....代码.....被 \(y

HDU 4553 约会安排 (区间合并)【线段树】

<题目链接> 寒假来了,又到了小明和女神们约会的季节.  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复"呵呵",所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事.  我们已知小明一共有T的空闲时间,期间会有很多女神或者基友来找小明.  作为一个操作系统曾经怒考71分的大神,小明想到了一个算法,即"首次适应算法",根据操作系统课本的描述,就是找一段最靠前的符

约会安排---hdu4553(线段树,麻烦的区间覆盖)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 算是poj3667的加强版,建立两颗线段树,一个是DS区间,另一个是NS区间.那么根据题意,如果是DS的请求,那么首先查找DS的区间,如果有满足的区间就更新DS区间,NS的区间不需要更新.如果是NS的请求,首先看DS区间是否有满足的区间,否则查找NS区间,如果有就同时更新DS区间和NS区间.那么可以归纳为,只要是NS的请求,就同时更新两颗线段树,否则只更新DS的线段树. 注意输出要从Outpu