Stanford Local 2016 G "Ground Defense"(线段树)
题意:
有 n 个城市,编号 1~n;
有两种操作:Update,Query
Update:
E i s a d
更新区间[ i,i+d-1 ], i 节点降落 s 人, i+1 节点降落 s+a 人, i+2 节点降落 s+2*a 人,......, i+d-1 节点降落 s+(d-1)*a 人;
W i s a d
更新区间[ i-d+1,i ], i 节点降落 s 人, i-1 节点降落 s+a 人, i-2 节点降落 s+2*a 人,......, i-d+1 节点降落 s+(d-1)*a 人;
简言之,从 i 节点下降 s 人开始,向东(右),西(左)下降的人数依次 +a;
Query: i
查询在节点 i 降落的总人数。
题解:
看到这道题,第一反应是线段树区间更新,那具体怎么个更新法呢?
首先看线段树中定义的元素:
struct SegmentTree
{
int l,r;
ll s;//l处增加s人
ll a;//从l到r依次变化a人
int mid()
{
return l+((r-l)>>);
}
}segTree[*maxn];
定义Update()函数,具体如下:
void Update(int l,int r,int pos,ll s,ll a)
{
if(segTree[pos].l == l && segTree[pos].r == r)
{
segTree[pos].s += s;//pos节点中的s增加s
segTree[pos].a += a;//pos节点中的a增加a
return ;
}
pushDown(pos);//向下更新 int mid=segTree[pos].mid();
if(r <= mid)
Update(l,r,ls(pos),s,a);
else if(l > mid)
Update(l,r,rs(pos),s,a);
else
{
ll d=mid+-l;
Update(l,mid,ls(pos),s,a);
Update(mid+,r,rs(pos),s+d*a,a);//注意右儿子更新的s值
}
}
如果更新操作为 E i s a d :
调用函数 Update( i , i+d-1 , 1 , s , a );
反之,如果更新操作为 W i s a d ⇔ E (i-d+1) ( s+(d-1)*a ) (-a) d
调用函数 Update( (i-d+1) , i , 1 , s+(d-1)*a , -a );
更新函数中的pushDown()函数是非常重要的,其决定了此算法的正确与否:
//将pos节点更新的状态传给儿子节点
void pushDown(int pos)
{
ll &s=segTree[pos].s;
ll &a=segTree[pos].a;
if(s)//如果s不为0,说明在这之前曾更新过pos节点
{
//左儿子的更新
segTree[ls(pos)].s += s;
segTree[ls(pos)].a += a; /**
右儿子的更新操作
注意 segTree[rs(pos)].s 增加的值
具体原因留给读者自己思索
*/
segTree[rs(pos)].s += s+a*(segTree[rs(pos)].l-segTree[ls(pos)].l);
segTree[rs(pos)].a += a;
}
s=;
a=;
}
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=5e5+; int n,m;
struct SegmentTree
{
int l,r;
ll s;//l处增加s人
ll a;//从l到r依次增加a
int mid()
{
return l+((r-l)>>);
}
}segTree[*maxn]; void pushDown(int pos)
{
ll &s=segTree[pos].s;
ll &a=segTree[pos].a;
if(s)
{
segTree[ls(pos)].s += s;
segTree[ls(pos)].a += a; /**
右儿子的更新操作
注意 segTree[rs(pos)].s 增加的值
具体原因留给读者自己思索
*/
segTree[rs(pos)].s += s+a*(segTree[rs(pos)].l-segTree[ls(pos)].l);
segTree[rs(pos)].a += a;
}
s=;
a=;
}
void buildSegTree(int l,int r,int pos)
{
segTree[pos].l=l;
segTree[pos].r=r;
segTree[pos].s=;
segTree[pos].a=;
if(l == r)
return ; int mid=l+((r-l)>>);
buildSegTree(l,mid,ls(pos));
buildSegTree(mid+,r,rs(pos));
}
void Update(int l,int r,int pos,ll s,ll a)
{
if(segTree[pos].l == l && segTree[pos].r == r)
{
segTree[pos].s += s;
segTree[pos].a += a;
return ;
}
pushDown(pos);//向下更新 int mid=segTree[pos].mid();
if(r <= mid)
Update(l,r,ls(pos),s,a);
else if(l > mid)
Update(l,r,rs(pos),s,a);
else
{
ll d=mid+-l;
Update(l,mid,ls(pos),s,a);
Update(mid+,r,rs(pos),s+d*a,a);//注意右儿子更新的s值
}
}
ll Query(int x,int pos)
{
if(segTree[pos].l == segTree[pos].r)
return segTree[pos].s;
pushDown(pos); int mid=segTree[pos].mid();
if(x <= mid)
return Query(x,ls(pos));
else
return Query(x,rs(pos));
}
int main()
{
// freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
int test;
scanf("%d",&test);
while(test--)
{
scanf("%d%d",&m,&n);
buildSegTree(,n,);
while(m--)
{
char order[];
scanf("%s",order);
if(order[] == 'U')
{
char x[];
int i,s,a,d;
scanf("%s%d%d%d%d",x,&i,&s,&a,&d);
if(x[] == 'E')
{
//r=min()是为了防止数据出错使得 i+d-1 > n
int r=min(n,i+d-);
Update(i,r,,s,a);
}
else
{
//l=max()是为了防止数据出错使得 i-d+1 < 1
int l=max(,i-d+);
Update(l,i,,1ll*s+1ll*a*(d-),-a);
}
}
else
{
int i;
scanf("%d",&i);
printf("%lld\n",Query(i,));
}
}
}
return ;
}
Stanford Local 2016 G "Ground Defense"(线段树)的更多相关文章
- BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流
BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流 Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1 ...
- BZOJ 4276: [ONTAK2015]Bajtman i Okrągły Robin [线段树优化建边]
4276: [ONTAK2015]Bajtman i Okrągły Robin 题意:\(n \le 5000\)个区间\(l,r\le 5000\),每个区间可以选一个点得到val[i]的价值,每 ...
- Educational Codeforces Round 51 (Rated for Div. 2) G. Distinctification(线段树合并 + 并查集)
题意 给出一个长度为 \(n\) 序列 , 每个位置有 \(a_i , b_i\) 两个参数 , \(b_i\) 互不相同 ,你可以进行任意次如下的两种操作 : 若存在 \(j \not = i\) ...
- 【BZOJ4276】[ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流
[BZOJ4276][ONTAK2015]Bajtman i Okrągły Robin Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2 ...
- codeforces 626 G. Raffles(线段树+思维+贪心)
题目链接:http://codeforces.com/contest/626/problem/G 题解:这题很明显买彩票肯定要买贡献最大的也就是说买p[i]*(num[i]+1)/(num[i]+a[ ...
- LYOI 2016 Summer 函数 【线段树】
<题目链接> 题目大意: fqk 退役后开始补习文化课啦,于是他打开了数学必修一开始复习函数,他回想起了一次函数都是 f(x)=kx+b的形式,现在他给了你n个一次函数 fi(x)=kix ...
- ACM-ICPC 2018 徐州赛区网络预赛-G Trace(线段树的应用
Problem:Portal传送门 Problem:Portal传送门 原题目描述在最下面. 我理解的题意大概是:有n次涨潮和退潮,每次的范围是个x×y的矩形,求n次涨退潮后,潮水痕迹的长度. ...
- Stanford Local 2016 E "Election of Evil"(搜索(正解)或并查集(划掉))
传送门 题意: 给出集合U,V,集合U有n个元素,集合V有m个元素: 有 m 个操作,mi : s1 s2 有一条s1指向s2的边(s1,s2可能属于第三个集合,暂且称之为K集合): 指向边具有传递性 ...
- 华中农业大学第四届程序设计大赛网络同步赛 G.Array C 线段树或者优先队列
Problem G: Array C Time Limit: 1 Sec Memory Limit: 128 MB Description Giving two integers and and ...
随机推荐
- java 中文乱码以及转码
查看此文章需要对字符集编码有一定的认识:任意门:字符集编码基础 一.字符串的内部表示? 重点:字符串在java(指在JVM中.在内存中)中统一用unicode表示( 即utf-16 LE) , 下面解 ...
- PJSUA2开发文档--第八章 好友(Buddy)类
8 好友(存在)Buddy PJSUA2的功能是围绕Buddy类为中心展开的.该类表示一个远端好友(伙伴,一个人或一个SIP端点). 8.1 子类化Buddy类 要使用Buddy类,通常应创建子类, ...
- 使用Python的列表推导式计算笛卡儿积
笛卡儿积: 笛卡儿积是一个列表, 列表里的元素是由输入的可迭代类型的元素对构 成的元组,因此笛卡儿积列表的长度等于输入变量的长度的乘积, 如下图: 如果你需要一个列表,列表里是 3 种不同尺寸的 T ...
- MySQL 基础知识梳理学习(一)----系统数据库
information_schema 此数据库是MySQL数据库自带的,主要存储数据库的元数据,保存了关于MySQL服务器维护的所有其他数据库的信息,如数据库名.数据库表.表列的数据类型及访问权限等. ...
- python 结巴分词学习
结巴分词(自然语言处理之中文分词器) jieba分词算法使用了基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能生成词情况所构成的有向无环图(DAG), 再采用了动态规划查找最大概率路径,找出基于 ...
- spark-RDD源码分析
http://stark-summer.iteye.com/blog/2178096 RDD的核心方法: 首先看一下getPartitions方法的源码: getPartitions返回的是一系列pa ...
- hbase 迁库移库步骤
1 将数据导出 hbase org.apache.hadoop.hbase.mapreduce.Export t_zyzx_grzyfwtjxxb /hbase/data_backup/2018103 ...
- day17-异常处理
今天的内容比较少,只是单独的异常处理 开始今日份整理 1.异常 定义:异常时错误发生的信号,一旦出错,并且程序没有处理这个错误,就会抛出异常,并且程序会运行中止 2.异常的分类 2.1语法错误:pyt ...
- Qt License 解读
对于桌面和移动平台应用 官方说明如下 Qt for Application Development lets you create applications for desktop and mobil ...
- java高级---->Thread之ScheduledExecutorService的使用
ScheduledExecutorService的主要作用就是可以将定时任务与线程池功能结合使用.今天我们来学习一下ScheduledExecutorService的用法.我们都太渺小了,那么容易便湮 ...