Mango DS Traning #49 ---线段树3 解题手记

时间:2022-08-24 11:21:09

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 解题手记的更多相关文章

  1. Mango DS Training &num;48 ---线段树2 解题手记

    Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38966#overview A.Count Color ...

  2. HDU 1754 线段树入门解题报告

    ---恢复内容开始--- 题意:给定区间,每个人的成绩, Q次询问,求每次询问区间中的最大值 思路:构造线段树 代码: #include<stdio.h> #include<algo ...

  3. POJ 3264 线段树入门解题报告

    题意:给n个值, Q次询问, 每次询问给定一个区间, 要求输出该区间最大最小值之差 思路:暴力的话每次询问都要遍历多次for循环一定会超时, 用线段树记录区间的信息(左边界右边界, 该区间最大值最小值 ...

  4. &lbrack;NOIP2016 DAY1 T2&rsqb;天天爱跑步-&lbrack;差分&plus;线段树合并&rsqb;&lbrack;解题报告&rsqb;

    [NOIP2016 DAY1 T2]天天爱跑步 题面: B[NOIP2016 DAY1]天天爱跑步 时间限制 : - MS 空间限制 : 565536 KB 评测说明 : 2s Description ...

  5. 洛谷 P3373 【模板】线段树 2 解题报告

    P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上\(x\) 2.将某区间每一个数加上\(x\) 3.求出某区间每一个数的和 输入输出格式 ...

  6. ACM Minimum Inversion Number 解题报告 -线段树

    C - Minimum Inversion Number Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d &a ...

  7. poj 2777 Count Color&lpar;线段树区区&plus;染色问题&rpar;

    题目链接:  poj 2777 Count Color 题目大意:  给出一块长度为n的板,区间范围[1,n],和m种染料 k次操作,C  a  b  c 把区间[a,b]涂为c色,P  a  b 查 ...

  8. BZOJ2733 &lbrack;HNOI2012&rsqb;永无乡 【线段树合并】

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  9. 洛谷P4556 雨天的尾巴 线段树

    正解:线段树合并 解题报告: 传送门! 考虑对树上的每个节点开一棵权值线段树,动态开点,记录一个max(num,id)(这儿的id,define了一下,,,指的是从小到大排QAQ 然后修改操作可以考虑 ...

随机推荐

  1. Distributed2:Linked Server Login 添加和删除

    一,通过 sys.sp_addlinkedsrvlogin 创建Linked Server的Login 当在local Server 上需要访问Linked Server时,Local Server ...

  2. treap 模版

    struct Treap { struct node { node *son[]; int key,siz,wei,cnt; node(int _key,node *f) { son[]=son[]= ...

  3. Foundation Sorting&colon; Single List Insertion Sort

    /* List Insertion Sorting. * Implementation history:. * 2013-09-15, Mars Fu, first version. */ #incl ...

  4. oracle11g dataguard 完全手册&lpar;转&rpar;

    转自:http://www.cnblogs.com/tippoint/archive/2013/04/18/3029019.html 一.前言:   网络上关于dataguard的配置文章很多,但是很 ...

  5. CCNA网络工程师学习进程(7)路由器的路由配置

        前面一节已经介绍了路由器的端口配置,接着我们介绍路由器的路由配置:静态路由.默认路由和浮动路由的配置:动态路由协议的配置,包括RIP.IGRP.EIGRP和OSPF.     (1)路由器的基 ...

  6. Spring容器的简单实现(IOC原理)

    引言:容器是什么?什么是容器?Spring容器又是啥东西?我给Spring容器一个对象名字,为啥能给我创建一个对象呢? 一.容器是装东西的,就像你家的水缸,你吃饭的碗等等. java中能作为容器的有很 ...

  7. IE 下js里面new Date&lpar;&quot&semi;2017-07-11 08&colon;00&colon;00&quot&semi;&rpar; 出现NAN的问题以及解决方法

    在js里面用了这个方法   var  $date= new Date("2017-07-11 08:00:00") 可是打印的时候为 NAN.查了下  只有IE下有这个问题,然后我 ...

  8. Boost&colon;&colon;bind使用详解

    1.Boost::bind 在STL中,我们经常需要使用bind1st,bind2st函数绑定器和fun_ptr,mem_fun等函数适配器,这些函数绑定器和函数适配器使用起来比较麻烦,需要根据是全局 ...

  9. Redis简介&plus;常用命令

    Redis=REmote DIctionary Server Redis是一个使用C语言编写的开源数据库,是高性能的key-value数据库,是内存数据库,支持数据持久化. Redis常用数据类型: ...

  10. WPF自定义控件的自定义属性绑定后不更新问题

    原文:WPF自定义控件的自定义属性绑定后不更新问题 需要在绑定时设置属性变更触发 UpdateSourceTrigger=PropertyChanged 例如: <Border CornerRa ...