E - Tunnel Warfare HDU - 1540

对这个题目的思考:首先我们已经意识到这个是一个线段树,要利用线段树来解决问题,但是怎么解决呢,这个摧毁和重建的操作都很简单,但是这个查询怎么查呢,

这个是不是要判断这一个点左边和右边最远的距离,然后相加起来就可以了,所以就是维护一个区间最左边和最右边的值,然后把他们合并就是最大值。

这个最左边的值 pre_max = 子左节点的 pre_max

如果这个 pre_max==len 那就可以合并子右节点的 pre_max

最右值同理

这个都知道了就只剩下细心一点写这个题目了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <stack>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
typedef long long ll;
struct node
{
int l, r, len;
int pre_max, last_max;
}tree[maxn*]; void push_up(int id)
{
tree[id].pre_max = tree[id << ].pre_max;
tree[id].last_max = tree[id << | ].last_max;
if (tree[id << ].len == tree[id << ].pre_max) tree[id].pre_max += tree[id<<|].pre_max;
if (tree[id << | ].len == tree[id << | ].last_max) tree[id].last_max += tree[id << ].last_max;
// printf("tree[%d].max=%d tree[%d].min=%d\n", id, tree[id].pre_max, id, tree[id].last_max);
// printf("tree[%d].max=%d tree[%d].min=%d\n", id << 1, tree[id << 1].pre_max, id << 1, tree[id << 1].last_max);
// printf("tree[%d].max=%d tree[%d].min=%d\n", id << 1 | 1, tree[id << 1 | 1].pre_max, id << 1 | 1, tree[id << 1 | 1].last_max);
} void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].len = r - l + ;
if(l==r)
{
tree[id].last_max = tree[id].pre_max = ;
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
push_up(id);
} void update(int id,int pos,int val)
{
//printf("id=%d pos=%d val=%d\n", id, pos, val);
int l = tree[id].l;
int r = tree[id].r;
if(l==r)
{
tree[id].last_max = tree[id].pre_max = val;
return;
}
int mid = (l + r) >> ;
if (pos <= mid) update(id << , pos, val);
else update(id << | , pos, val);
push_up(id);
} int query_pre(int id,int x,int y)
{
int l = tree[id].l;
int r = tree[id].r;
//printf("id=%d l=%d r=%d x=%d y=%d\n", id, l, r, x, y);
if(x<=l&&y>=r) return tree[id].pre_max;
int mid = (l + r) >> ;
int ans = , res = ;
if (x <= mid) ans = query_pre(id << , x, y);
if (y > mid) res = query_pre(id << | , x, y);
// printf("id=%d res=%d ans=%d\n", id, res, ans);
if (ans >= mid - x + ) return ans += res;//这个区间长度就是mid-x+1 因为mid 是在里面的所以要+1
return ans;
} int query_last(int id, int x, int y) {
int l = tree[id].l;
int r = tree[id].r;
//printf("id=%d l=%d r=%d x=%d y=%d \n", id, l, r, x, y);
if (x <= l && y >= r) return tree[id].last_max;
int mid = (l + r) >> ;
int ans = , res = ;
if (x <= mid) ans = query_last(id << , x, y);
if (y > mid) res = query_last(id << | , x, y);
//printf("Ans=%d res=%d\n", ans, res);
if (res >= y - mid) res += ans;//区间长度为 y-mid mid不在里面
return res;
} int main()
{
int m, n;
while(scanf("%d%d", &n, &m)!=EOF)
{
stack<int>sta;
build(, , n);
while(m--)
{
char s[];
int x;
scanf("%s", s);
if(s[]=='D')
{
scanf("%d", &x);
sta.push(x);
update(, x, );
}
else if(s[]=='R')
{
if(!sta.empty())
{
int num = sta.top(); sta.pop();
update(, num, );
}
}
else if(s[]=='Q')
{
scanf("%d", &x);
int ans = query_pre(, x, n);
ans += query_last(, , x);
if(ans) printf("%d\n", ans - );
else printf("0\n");
}
}
}
return ;
}

线段树的区间合并

 
对这个题目的思考:这个题目不太会写,对于区间合的基本套路还是不太熟悉,这个题目看了题解之后(推荐题解 题解传送门)还是很清楚的。
我们知道这个是一个区间合并的线段树,和区间息息相关,这个要求长度为 w 的最左边的区间,还要求起点。
长度确定,所以我们就一个域是求最大长度的,因为要最左边的区间,而且我们要求最大长度就有合并操作,
所以我们要确定一个从左边开始最长的和从右边开始最长的,这个就和上面的差不多。
这个就是大致思路,剩下就是一些细节了。
一定要仔细点写,然后wa到哭

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <stack>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
typedef long long ll;
struct node {
int l, r, lazy, len;
int pre_max, last_max, max;
}tree[maxn * ]; void push_up(int id) {
tree[id].pre_max = tree[id << ].pre_max;
tree[id].last_max = tree[id << | ].last_max;
if (tree[id << ].pre_max == tree[id << ].len) tree[id].pre_max += tree[id << | ].pre_max;
if (tree[id << | ].last_max == tree[id << | ].len) tree[id].last_max += tree[id << ].last_max;
tree[id].max = max(max(tree[id<<].max, tree[id<<|].max), tree[id << ].last_max + tree[id << | ].pre_max);
//printf("tree[%d].pre_max=%d tree[%d].last_max=%d\n", id, tree[id].pre_max, id, tree[id].last_max);
} void build(int id, int l, int r) {
tree[id].l = l;
tree[id].r = r;
tree[id].lazy = -;
tree[id].len = tree[id].last_max = tree[id].pre_max = tree[id].max = r - l + ;
//printf("tree[%d].pre_max=%d tree[%d].last_max=%d\n", id, tree[id].pre_max, id, tree[id].last_max);
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
} void push_down(int id) {
if (tree[id].lazy != -) {
tree[id << ].lazy = tree[id << | ].lazy = tree[id].lazy; if (tree[id].lazy) {
tree[id << ].last_max = tree[id << ].pre_max = tree[id << ].max = tree[id << ].len;
tree[id << | ].last_max = tree[id << | ].pre_max = tree[id << | ].max = tree[id << | ].len;
}
else {
tree[id << ].last_max = tree[id << ].pre_max = tree[id << ].max = ;
tree[id << | ].last_max = tree[id << | ].pre_max = tree[id << | ].max = ;
}
tree[id].lazy = -;
}
} void update(int id, int x, int y, int val) {
// printf("id=%d x=%d y=%d val=%d\n", id, x, y, val);
int l = tree[id].l;
int r = tree[id].r;
if (x == l && y == r) {
tree[id].lazy = val;
if (val) tree[id].last_max = tree[id].pre_max = tree[id].max = tree[id].len;
else tree[id].last_max = tree[id].pre_max = tree[id].max = ;
return;
}
push_down(id);
int mid = (l + r) >> ;
if (y <= mid) update(id << , x, y, val);
else if (mid + <= x) update(id << | , x, y, val);
else {
update(id << , x, mid, val);
update(id << | , mid + , y, val);
}
push_up(id);
} int query(int id, int val) {
int l = tree[id].l;
int r = tree[id].r;
//printf("id=%d l=%d r=%d\n", id, l, r);
if (l == r) return l;
int mid = (l + r) >> ;
push_down(id);
if (tree[id << ].max >= val) return query(id << , val);
//printf("id1=%d\n", id);
if (tree[id << ].last_max + tree[id << | ].pre_max >= val) return mid - tree[id << ].last_max + ;
//printf("tree[%d].last=%d tree[%d].pre=%d id2=%d\n", id<<1,tree[id<<1].last_max,id<<1|1,tree[id<<1|1].pre_max,id);
return query(id << | , val);
} int main() {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
build(, , n);
while (m--) {
int opt, x, y;
scanf("%d", &opt);
if (opt == ) {
scanf("%d", &x);
if (tree[].max < x) {
printf("0\n");
continue;
}
int ans = query(, x);
if (ans) update(, ans, ans + x - , );
printf("%d\n", ans);
}
else {
scanf("%d%d", &x, &y);
update(, x, x + y - , );
}
}
}
return ;
}

线段树

 

G - 约会安排

这个题目 :

如果是 DS 就是普通的查找,如果找到就输出最靠前的时间点,这个和上面的操作很像,然后更新。

如果是 NS 就要进行两次查找,第一次是普通查找,没有找到就是二级查找,这个二级查找就是一种覆盖,然后更新。

如果是 study 那就是清空为0 的操作。

这个就是相当于建了两棵树,一颗女神树,一颗基友树,处理女神树的时候要更新基友树,但是处理基友树就不需要更新女神树。

这个题目一定要注意 输出答案

描述中的“如果找到,就说“X,let’s fly”(此处,X为开始时间)…"
和Output中的 “X,let's fly”
里的“ ’ ”和 “ ' ” 不是一个符号,别复制错了!!!

#include <cstdio>//描述中的“如果找到,就说“X,let’s fly”(此处,X为开始时间)…"
#include <cstdlib>//和Output中的 “X, let's fly”
#include <cstring>//里的“ ’ ”和 “ ' ” 不是一个符号,别复制错了!!!
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <stack>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
typedef long long ll;
struct node {
int len;
int lsum, rsum, sum;//1 级的
int lmax, rmax, max;//2 级的
}tree[maxn * ]; void build(int id, int l, int r) {
tree[id].max = tree[id].lmax = tree[id].rmax = r - l + ;
tree[id].len = tree[id].lsum = tree[id].rsum = tree[id].sum = r - l + ;
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
} void push_up(int id) {
tree[id].lsum = tree[id << ].lsum;
tree[id].rsum = tree[id << | ].rsum;
if (tree[id << ].lsum == tree[id << ].len) tree[id].lsum += tree[id << | ].lsum;
if (tree[id << | ].rsum == tree[id << | ].len) tree[id].rsum += tree[id << ].rsum;
tree[id].sum = max(max(tree[id << ].sum, tree[id << | ].sum), tree[id << ].rsum + tree[id << | ].lsum);
tree[id].sum = max(tree[id].sum, tree[id].lsum);
tree[id].sum = max(tree[id].sum, tree[id].rsum); tree[id].lmax = tree[id << ].lmax;
tree[id].rmax = tree[id << | ].rmax;
if (tree[id << ].lmax == tree[id << ].len) tree[id].lmax += tree[id << | ].lmax;
if (tree[id << | ].rmax == tree[id << | ].len) tree[id].rmax += tree[id << ].rmax;
tree[id].max = max(max(tree[id << ].max, tree[id << | ].max), tree[id << ].rmax + tree[id << | ].lmax);
tree[id].max = max(tree[id].max, tree[id].lmax);
tree[id].max = max(tree[id].max, tree[id].rmax);
} void push_down(int id) {
if(tree[id].max==tree[id].len)
{
tree[id << ].max = tree[id << ].lmax = tree[id << ].rmax = tree[id << ].len;
tree[id << | ].max = tree[id << | ].lmax = tree[id << | ].rmax = tree[id << | ].len;
}
if(tree[id].max==)
{
tree[id << ].max = tree[id << ].lmax = tree[id << ].rmax = ;
tree[id << | ].max = tree[id << | ].lmax = tree[id << | ].rmax = ;
}
if(tree[id].sum==tree[id].len)
{
tree[id << ].sum = tree[id << ].lsum = tree[id << ].rsum = tree[id << ].len;
tree[id << | ].sum = tree[id << | ].lsum = tree[id << | ].rsum = tree[id << | ].len;
}
if(tree[id].sum==)
{
tree[id << ].sum = tree[id << ].lsum = tree[id << ].rsum = ;
tree[id << | ].sum = tree[id << | ].lsum = tree[id << | ].rsum = ;
}
} void update(int id, int l, int r, int x, int y, int val) {
if (x <= l && y >= r) {
if (val == ) {
tree[id].max = tree[id].lmax = tree[id].rmax = ;
tree[id].sum = tree[id].lsum = tree[id].rsum = ;
}
if (val == ) {
tree[id].sum = tree[id].lsum = tree[id].rsum = ;
}
if (val == ) {
tree[id].max = tree[id].lmax = tree[id].rmax = tree[id].len;
tree[id].sum = tree[id].lsum = tree[id].rsum = tree[id].len;
}
return;
}
push_down(id);
int mid = (l + r) >> ;
if (x <= mid) update(id << , l, mid, x, y, val);
if (y > mid) update(id << | , mid + , r, x, y, val);
push_up(id);
} int query_1(int id, int l, int r, int val) {
if (l == r) return l;
int mid = (l + r) >> ;
push_down(id);
if (tree[id << ].sum >= val) return query_1(id << , l, mid, val);
if (tree[id << ].rsum + tree[id << | ].lsum >= val) return mid - tree[id << ].rsum + ;
return query_1(id << | , mid + , r, val);
} int query_2(int id,int l,int r,int val)
{
if (l == r) return l;
int mid = (l + r) >> ;
push_down(id);
if (tree[id << ].max >= val) return query_2(id << , l, mid, val);
if (tree[id << ].rmax + tree[id << | ].lmax >= val) return mid - tree[id << ].rmax + ;
return query_2(id << | , mid + , r, val);
} int main()
{
int t;
scanf("%d", &t);
for(int cas=;cas<=t;cas++)
{
int n, m, x, y;
scanf("%d%d", &n, &m);
build(, , n);
printf("Case %d:\n", cas);
while(m--)
{
char s[];
scanf("%s", s);
if(s[]=='D')
{
scanf("%d", &x);
if(tree[].sum<x)
{
printf("fly with yourself\n");
continue;
}
int ans = query_1(, , n, x);
printf("%d,let's fly\n", ans);
update(, , n, ans, x + ans - , );
}
if(s[]=='N')
{
scanf("%d", &x);
if(tree[].sum>=x)
{
int ans = query_1(, , n, x);
printf("%d,don't put my gezi\n", ans);
update(, , n, ans, x + ans - , );
continue;
}
if(tree[].max<x)
{
printf("wait for me\n");
continue;
}
int ans = query_2(,,n,x);
printf("%d,don't put my gezi\n", ans);
update(, , n, ans, x + ans - , );
}
if(s[]=='S')
{
scanf("%d%d", &x, &y);
update(, , n, x, y, );
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
}

线段树

E - Tunnel Warfare HDU - 1540 F - Hotel G - 约会安排 HDU - 4553 区间合并的更多相关文章

  1. hdu 4453 约会安排(线段树区间合并)

    约会安排 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  2. M - 约会安排 - hdu 4553

    寒假来了,又到了小明和女神们约会的季节.  小明虽为�丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑,由于数量 ...

  3. 约会安排HDU - 4553

    寒假来了,又到了小明和女神们约会的季节.  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复"呵呵",所以,小明的最爱就是和女神们约会.与此同时,也有很多基 ...

  4. M - 约会安排 HDU - 4553 线段树 (最长连续段)

    中文题面 思路:维和两个区间  一个是女神区间 一个是基友区间  如果是基友要预约时间 直接在基友区间查询可满足的起点 (这里先判tree[1].m >=length也就是有没有这样的区间满足时 ...

  5. HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

    题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  相应区间的LCIS长度(lcis)  相应区间以左 ...

  6. 约会安排 HDU - 4553(线段树区间查询,区间修改,区间合并)

    题目: 寒假来了,又到了小明和女神们约会的季节.  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑, ...

  7. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  8. hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

    Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  9. hdu 1540 Tunnel Warfare (区间线段树(模板))

    http://acm.hdu.edu.cn/showproblem.php?pid=1540 Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) ...

随机推荐

  1. Java 理论与实践: 流行的原子

    Java 理论与实践: 流行的原子 新原子类是 java.util.concurrent 的隐藏精华 在 JDK 5.0 之前,如果不使用本机代码,就不能用 Java 语言编写无等待.无锁定的算法.在 ...

  2. AJ学IOS 之二维码学习,快速打开相机读取二维码

    AJ分享,必须精品 上一篇文章写了怎么生成二维码,这儿就说说怎么读取吧,反正也很简单,iOS封装的太强大了 步骤呢就是这样: 读取二维码需要导入AVFoundation框架#import <AV ...

  3. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(九)之Interfaces

    Interfaces and abstract classes provide more structured way to separate interface from implementatio ...

  4. unity使用Animator做一个简单的动画

    1.在unity的物体上添加Animator组件 2.在Project下的Assets下添加Animator Controller 3.在Animator Controller添加动作 4.在动作之间 ...

  5. Salesforce元数据入门指南,管理员必看!

    元数据是Salesforce基础架构的核心,是Salesforce中的核心组件或功能.没有元数据,大部分功能都无法实现. 但是,某些Salesforce管理员仍然很难掌握元数据的整个范围,并且无法充分 ...

  6. 你知道如何自动保存 Spring Boot 应用进程号吗

    1. 前言 欢迎阅读 Spring Boot 2 实战 系列文章. PID 对于系统运维来说并不陌生,但是对于一些开发者特别是新手还是要简单介绍一下的.它是 Process ID 的简称,是系统分配给 ...

  7. re模块语法—python正则表达式

    用字符串匹配实现 对于简单的匹配查找,可以通过字符串匹配实现,比如:查找以”hello”开头的字符串 此时就可以正确查找出以start开始的字符串了 python中的正则表达式模块 在python中为 ...

  8. Matlab学习-(4)

    1. 函数 1.1 原始方法 之前我调用函数的方法是,首先写好函数文件,然后保存,然后在主函数中调用.这种方法的不足在于会导致你的工作目录的文件太多,从而导致很乱.在网上找了一些解决方法. 1.2 本 ...

  9. java多线程3:原子性,可见性,有序性

    概念 在了解线程安全问题之前,必须先知道为什么需要并发,并发给我们带来什么问题. 为什么需要并发,多线程? 时代的召唤,为了更充分的利用多核CPU的计算能力,多个线程程序可通过提高处理器的资源利用率来 ...

  10. Suctf知识记录&&PHP代码审计,无字母数字webshell&&open_basedir绕过&&waf+idna+pythonssrf+nginx

    Checkin .user.ini构成php后门利用,设置auto_prepend_file=01.jpg,自动在文件前包含了01.jpg,利用.user.ini和图片马实现文件包含+图片马的利用. ...