传送门

题意:

  有 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"(线段树)的更多相关文章

  1. 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 ...

  2. 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]的价值,每 ...

  3. Educational Codeforces Round 51 (Rated for Div. 2) G. Distinctification(线段树合并 + 并查集)

    题意 给出一个长度为 \(n\) 序列 , 每个位置有 \(a_i , b_i\) 两个参数 , \(b_i\) 互不相同 ,你可以进行任意次如下的两种操作 : 若存在 \(j \not = i\) ...

  4. 【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 ...

  5. codeforces 626 G. Raffles(线段树+思维+贪心)

    题目链接:http://codeforces.com/contest/626/problem/G 题解:这题很明显买彩票肯定要买贡献最大的也就是说买p[i]*(num[i]+1)/(num[i]+a[ ...

  6. LYOI 2016 Summer 函数 【线段树】

    <题目链接> 题目大意: fqk 退役后开始补习文化课啦,于是他打开了数学必修一开始复习函数,他回想起了一次函数都是 f(x)=kx+b的形式,现在他给了你n个一次函数 fi(x)=kix ...

  7. ACM-ICPC 2018 徐州赛区网络预赛-G Trace(线段树的应用

    Problem:Portal传送门 Problem:Portal传送门  原题目描述在最下面.  我理解的题意大概是:有n次涨潮和退潮,每次的范围是个x×y的矩形,求n次涨退潮后,潮水痕迹的长度.   ...

  8. Stanford Local 2016 E "Election of Evil"(搜索(正解)或并查集(划掉))

    传送门 题意: 给出集合U,V,集合U有n个元素,集合V有m个元素: 有 m 个操作,mi : s1 s2 有一条s1指向s2的边(s1,s2可能属于第三个集合,暂且称之为K集合): 指向边具有传递性 ...

  9. 华中农业大学第四届程序设计大赛网络同步赛 G.Array C 线段树或者优先队列

    Problem G: Array C Time Limit: 1 Sec  Memory Limit: 128 MB Description Giving two integers  and  and ...

随机推荐

  1. C#窗体打包步骤

    1.在项目下选择InstallerProjects的Setup Project建立打包工具. 2.找到项目bin目录Release下的文件全部复制下来. 3.复制完之后全部粘贴到Application ...

  2. 虚拟机硬盘vmdk压缩瘦身并挂载到VirtualBox

    这个问题其实困扰了挺久的,一直没闲情去解决,网上搜索过很多压缩方法感觉都太麻烦太复杂,因最近在windows上搞docker就一并解决了. 压缩vmdk 首先下载DiskGenius,这工具很牛X,相 ...

  3. elasticsearch系列八:ES 集群管理(集群规划、集群搭建、集群管理)

    一.集群规划 搭建一个集群我们需要考虑如下几个问题: 1. 我们需要多大规模的集群? 2. 集群中的节点角色如何分配? 3. 如何避免脑裂问题? 4. 索引应该设置多少个分片? 5. 分片应该设置几个 ...

  4. lsof -i

    https://www.cnblogs.com/sparkbj/p/7161669.html 主要命令

  5. Spring Security(三十):9.5 Access-Control (Authorization) in Spring Security

    The main interface responsible for making access-control decisions in Spring Security is the AccessD ...

  6. 爬虫基础(四)-----MongoDB的使用

    ------------------------------------------------------------------------摆脱穷人思维 <四> :减少无意义的频繁决策 ...

  7. 03-JavaScript之数据类型

    JavaScript之数据类型 1.介绍 JavaScript数据类型分为两类:原始类型(primitive type)和对象类型(object type) 2.原始类型 数字 - number.字符 ...

  8. 家庭记账本小程序之增(java web基础版三)

    实现新增消费账单 1.main_left.jsp中该部分,调用add.jsp 2. add.jsp,提交到Servlet的add方法 <%@ page language="java&q ...

  9. jQuery 事件绑定

    在文档装载完成后,如果打算为元素绑定事件来完成某些操作,则可以使用 bind() 方法来对匹配元素进行特定事件的绑定,bind() 方法的调用格式为:bind( type [, data] , fn ...

  10. 洛谷P3957 跳房子(Noip2017普及组 T4)

    今天我们的考试就考到了这道题,在考场上就压根没有思路,我知道它是一道dp的题,但因为太弱还是写不出来. 下来评讲的时候知道了一些思路,是dp加上二分查找的方式,还能够用单调队列优化. 但看了网上的许多 ...