Mango DS Traning #49 ---线段树3 解题手记
Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38994#overview
B.Xenia and Bit Operations ----Codeforces 339D
线段树大水题。。每个节点维护一个flag,flag=1表示此时应与其兄弟节点做或(|)操作,flag=2表示做异或(^)操作,然后pushup...
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 140010 struct node
{
int sum,flag;
}tree[*N]; int two_n(int mi)
{
int i;
int res = ;
for(i=;i<=mi;i++)
{
res *= ;
}
return res;
} int a[N]; void pushup(int rt)
{
if(tree[*rt].flag == )
{
tree[rt].sum = tree[*rt].sum | tree[*rt+].sum;
tree[rt].flag = ;
}
else
{
tree[rt].sum = tree[*rt].sum ^ tree[*rt+].sum;
tree[rt].flag = ;
}
} void build(int l,int r,int rt)
{
if(l == r)
{
tree[rt].sum = a[l];
tree[rt].flag = ;
return;
}
int mid = (l+r)/;
build(l,mid,*rt);
build(mid+,r,*rt+);
pushup(rt);
} void update(int l,int r,int pos,int val,int rt)
{
if(l == r)
{
tree[rt].sum = val;
tree[rt].flag = ;
return;
}
int mid = (l+r)/;
if(pos<=mid)
update(l,mid,pos,val,*rt);
else
update(mid+,r,pos,val,*rt+);
pushup(rt);
} int main()
{
int n,m;
int i,pos,val;
while(scanf("%d%d",&n,&m)!=EOF)
{
int ken = two_n(n);
for(i=;i<=ken;i++)
{
scanf("%d",&a[i]);
}
build(,ken,);
for(i=;i<m;i++)
{
scanf("%d%d",&pos,&val);
update(,ken,pos,val,);
printf("%d\n",tree[].sum);
}
}
return ;
}
D.Copying Data ----Codeforces 292E
这题初看像线段树题,结果就是线段树题。怎么做树,维护哪些值呢? 开始想歪了,参照了别人的报告,于是知道,可以维护stx,sty值,这些值只在叶子节点上表现出来,因为只查叶子节点,不查区间,stx记录这个节点有没有被copy成a数组中的元素,stx == 0则代表还没被a给拷贝过来,否则,stx记录的是从x点开始拷贝k个的那个x值,等会后面要用到。sty则是随stx,stx要更新时,sty也要更新,sty初始为0,这时的sty为拷贝从b的y个位置开始的那个y值,总之,即输入x,y,k,stx记录x,sty记录y。最后查询pos节点,如果其stx或sty为0,说明这个节点还没有受到“侵染“,保持原来的b数组中的值,所以输出b[pos]。否则,已经收到”侵染“,输出a[pos-sty+stx],即从a中去与距离相等的元素,距离就是那个pos-sty,这时知道sty的作用了吧。。
代码:
/*3900KB 280ms*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 100010 int a[N],b[N];
int n,m; struct node
{
int stx,sty;
}tree[*N]; void build(int l,int r,int rt)
{
tree[rt].stx = tree[rt].sty = ;
if(l == r)
{
return;
}
int mid = (l+r)/;
build(l,mid,*rt);
build(mid+,r,*rt+);
} void pushdown(int rt)
{
if(tree[rt].stx)
{
tree[*rt].stx = tree[*rt+].stx = tree[rt].stx;
tree[*rt].sty = tree[*rt+].sty = tree[rt].sty;
tree[rt].stx = tree[rt].sty = ;
}
}
void change(int l,int r,int aa,int bb,int stx,int sty,int rt)
{
if(aa<=l&&bb>=r)
{
tree[rt].stx = stx;
tree[rt].sty = sty;
return;
}
pushdown(rt);
int mid = (l+r)/;
if(bb<=mid)
change(l,mid,aa,bb,stx,sty,*rt);
else if(aa>mid)
change(mid+,r,aa,bb,stx,sty,*rt+);
else
{
change(l,mid,aa,bb,stx,sty,*rt);
change(mid+,r,aa,bb,stx,sty,*rt+);
}
} node query(int l,int r,int pos,int rt)
{
if(l == r)
{
return tree[rt];
}
pushdown(rt);
int mid = (l+r)/;
if(pos<=mid)
return query(l,mid,pos,*rt);
return query(mid+,r,pos,*rt+);
} int main()
{ int i;
int x,y,k,pos;
int op;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(i=;i<=n;i++)
{
scanf("%d",&b[i]);
}
build(,n,);
for(i=;i<m;i++)
{
scanf("%d",&op);
if(op == )
{
scanf("%d%d%d",&x,&y,&k);
change(,n,y,y+k-,x,y,);
}
else
{
scanf("%d",&pos);
node ans = query(,n,pos,);
if(ans.stx == )
{
printf("%d\n",b[pos]);
}
else
{
printf("%d\n",a[pos-ans.sty+ans.stx]);
}
}
}
}
return ;
}
E.Circular RMQ ---Codeforces 52C
也是很简单的一道线段树,纯当练手了,还是那样维护,只不过可能换成两个区间查询和加值罢了。。还有值得一提的输入方式,因为比较坑爹的是输入不定,所以借鉴了别人的stringstream 方法,核心代码如下:
gets(buffer);
stringstream ss(buffer);
ss>>aa>>bb;
具体实现在下面。。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <utility>
#include <cstdlib>
#include <sstream>
using namespace std;
#define N 200010 struct node
{
lll mini;
lll addmark;
}tree[*N]; int n,m;
lll a[N]; void pushup(int rt)
{
tree[rt].mini = min(tree[*rt].mini,tree[*rt+].mini);
} void build(int l,int r,int rt)
{
tree[rt].addmark = ;
if(l == r)
{
tree[rt].mini = a[l];
return;
}
int mid = (l+r)/;
build(l,mid,*rt);
build(mid+,r,*rt+);
pushup(rt);
} void pushdown(int rt)
{
if(tree[rt].addmark)
{
tree[*rt].mini += tree[rt].addmark;
tree[*rt+].mini += tree[rt].addmark;
tree[*rt].addmark += tree[rt].addmark;
tree[*rt+].addmark += tree[rt].addmark;
tree[rt].addmark = ;
}
} void add(int l,int r,int aa,int bb,int val,int rt)
{
if(aa>r||bb<l)
return;
if(aa<=l&&bb>=r)
{
tree[rt].mini += val;
tree[rt].addmark += val;
return;
}
pushdown(rt);
int mid = (l+r)/;
if(aa<=mid)
add(l,mid,aa,bb,val,*rt);
if(bb>mid)
add(mid+,r,aa,bb,val,*rt+);
pushup(rt);
} lll query(int l,int r,int aa,int bb,int rt)
{
if(aa>r||bb<l)
return (lll)1e17;
if(aa<=l&&bb>=r)
{
return tree[rt].mini;
}
pushdown(rt);
int mid = (l+r)/;
if(bb<=mid)
return query(l,mid,aa,bb,*rt);
else if(aa>mid)
return query(mid+,r,aa,bb,*rt+);
else
{
return min(query(l,mid,aa,bb,*rt),query(mid+,r,aa,bb,*rt+));
}
} char buffer[]; int main()
{
int i,aa,bb;
lll val,ans;
while(scanf("%d",&n)!=EOF)
{
for(i=;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
build(,n,);
scanf("%d",&m);
gets(buffer);
for(i=;i<m;i++)
{
gets(buffer);
stringstream ss(buffer);
ss>>aa>>bb;
aa++,bb++;
if(ss>>val)
{
if(aa<=bb)
{
add(,n,aa,bb,val,);
}
else
{
add(,n,aa,n,val,);
add(,n,,bb,val,);
}
}
else
{
if(aa<=bb)
ans = query(,n,aa,bb,);
else
{
lll res = query(,n,aa,n,);
ans = query(,n,,bb,);
ans = min(ans,res);
}
printf("%I64d\n",ans);
}
}
}
return ;
}
H.Vessels ---Codeforces 371D
这道题我原来出的时候记得是线段树,但是后来看别人的代码,没看见一个用线段树写的,,我去。原来硬搞也能过。。难点是想到,。下面放我借鉴别人的代码吧:
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 200010 int cap[N],jp[N],a[N]; int main()
{
int n,m;
int i,j;
int op,pos,val;
int st;
while(scanf("%d",&n)!=EOF)
{
memset(cap,,sizeof(cap));
for(i=;i<=n;i++)
{
scanf("%d",&a[i]);
jp[i] = i;
}
scanf("%d",&m);
for(i=;i<m;i++)
{
scanf("%d",&op);
if(op == )
{
scanf("%d%d",&pos,&val);
st = jp[pos];
while(cap[st]+val>=a[st]&&st<=n)
{
val -= (a[st]-cap[st]);
cap[st] = a[st];
st++;
}
if(st<=n)
cap[st] += val;
for(j=jp[pos];j<st;j++)
{
jp[j] = st;
}
jp[pos] = st;
}
else
{
scanf("%d",&pos);
printf("%d\n",cap[pos]);
}
}
}
return ;
}
Mango DS Traning #49 ---线段树3 解题手记的更多相关文章
- Mango DS Training #48 ---线段树2 解题手记
Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38966#overview A.Count Color ...
- HDU 1754 线段树入门解题报告
---恢复内容开始--- 题意:给定区间,每个人的成绩, Q次询问,求每次询问区间中的最大值 思路:构造线段树 代码: #include<stdio.h> #include<algo ...
- POJ 3264 线段树入门解题报告
题意:给n个值, Q次询问, 每次询问给定一个区间, 要求输出该区间最大最小值之差 思路:暴力的话每次询问都要遍历多次for循环一定会超时, 用线段树记录区间的信息(左边界右边界, 该区间最大值最小值 ...
- [NOIP2016 DAY1 T2]天天爱跑步-[差分+线段树合并][解题报告]
[NOIP2016 DAY1 T2]天天爱跑步 题面: B[NOIP2016 DAY1]天天爱跑步 时间限制 : - MS 空间限制 : 565536 KB 评测说明 : 2s Description ...
- 洛谷 P3373 【模板】线段树 2 解题报告
P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上\(x\) 2.将某区间每一个数加上\(x\) 3.求出某区间每一个数的和 输入输出格式 ...
- ACM Minimum Inversion Number 解题报告 -线段树
C - Minimum Inversion Number Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d &a ...
- poj 2777 Count Color(线段树区区+染色问题)
题目链接: poj 2777 Count Color 题目大意: 给出一块长度为n的板,区间范围[1,n],和m种染料 k次操作,C a b c 把区间[a,b]涂为c色,P a b 查 ...
- BZOJ2733 [HNOI2012]永无乡 【线段树合并】
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 洛谷P4556 雨天的尾巴 线段树
正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...
随机推荐
- windows下redis启动报Creating Server TCP listening socket *:6379: bind: No such file or directory
解决方法: 按顺序输入如下命令就可以连接成功 # redis-cli.exe# > shutdown# > exit# redis-server.exe redis.windows.con ...
- 【使用 DOM】使用 Window 对象
1. 获取 Window 对象 可以用两种方式获得Window对象.正规的HTML5方式是在Document对象上使用defaultView属性.另一种是使用所有浏览器都支持的全局变量window . ...
- 【转载】iOS堆和栈的理解
操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segme ...
- RunLoop机制理解
一.浅识RunLoop RunLoop在开发中我们一直在用,但是没有注意他.要想理解RunLoop,首先我们需要先了解一下程序运行机制. 程序运行机制:我们都知道OC是运行时语言,也就是说对象的类型是 ...
- NSNumber和NSValue
在进行数据处理的时候,因为对象类型的不同, 并不能进行相应的数据处理,所以必须要进行数据类型的转换,这也就是NSNumber,NSValue这两类值对象出现的原因. 简而言之,NSNumber就是实现 ...
- iOS扫一扫功能开发
之前很多二维码扫描都是基于zxing做的,但是zxing用起来真的很麻烦,又一直不更新.随着iOS6退出历史舞台,终于可以使用iOS7以后,用系统的AVFoundation做的二维码扫描器了. 初始化 ...
- 使用ObjectOutputStream进行socket通信的时候出现固定读到四个字节乱码的问题
问题描述: 最近在写一个通信相关的项目,服务器端和客户端通过socket进行通信.本来想利用read的阻塞特性,服务器端和客户端按照一定的流程进行文件读写.结果发现客户端或者服务器read方法一直都返 ...
- UIViewController的edgesForExtendedLayout属性
UIViewController的edgesForExtendedLayout属性 想必大家都遇到一种情况,明明y坐标设置的是0,但是总是被讨厌的导航栏给遮住.比如下面这个情况: UILabel *l ...
- Android开发者的Git&Github(一)
安装Git: Linux(以Ubuntu为例): sudo apt-get install git-core Windows: 访问网址http://msysgit.github.io/下载安装包 下 ...
- 多线程基础(五)NSThread线程通信
5.多线程基础 线程间通信 什么叫线程间通信 在一个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另一个线程 在1个线程中执行完特定任务后, ...