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 #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. [NOIP2016 DAY1 T2]天天爱跑步-[差分+线段树合并][解题报告]

    [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(线段树区区+染色问题)

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

  8. BZOJ2733 [HNOI2012]永无乡 【线段树合并】

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

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

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

随机推荐

  1. javaweb学习之Servlet开发(二)

    javaweb学习总结(六)--Servlet开发(二) 一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个< ...

  2. HTML Window.document对象

    1.Window.document对象 一.找到元素: docunment.getElementById("id"):根据id找,最多找一个:    var a =docunmen ...

  3. 关于DOM操作的性能优化

    最著名的有关用js操作dom的观点是:js和dom是独立的小岛,用桥实现两者的联系,但桥很窄,要过路费,所以我们要尽最大可能减少过桥的次数.下面代码演示了用js操作dom的innerHTML,且一下修 ...

  4. ASP.NET MVC中将数据从Controller传递到视图

    ASP.NET MVC中将数据从Controller传递到视图方法 1.ViewData ViewData的类型是字典数据,key-value 如:ViewData["Data"] ...

  5. Python基础(5)--字典

    字典由多个键及与其对应的值构成的对组成(把键值对成为项),每个键和它的值之间用冒号(:)隔开,项之间用逗号(,)隔开,而整个字典由一对大括号括起来.空字典由两个大括号组成:{} 本文地址:http:/ ...

  6. iOS多线程技术

    iOS多线程技术主要分配NSThread.NSOperation和GCD.下边来简单的介绍一下吧. 随性一点,就不按照顺序来了.所以先介绍一下NSOperation. ---------------- ...

  7. page resizing

    <script type="text/javascript"> $(window).load(function () { var root; root = $(&quo ...

  8. JAVA基础学习day26--正则表达式

    一.正则表达式 1.1.概述 符合一规则的表达式:用于专门操作字符串. 正则表达式则必须依靠Pattern类与Matcher类,这两个类都在java.util.regex包中定义.Pattern类的主 ...

  9. iOS 学习 - 1.代理传值

    代理的目的是改变或传递控制链.允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针.可以减少框架复杂度.
另外一点,代理可以理解为java中的回调监听机制的一种类似 优点:1.避免子类化带 ...

  10. iOS:交换Button中图片与文字的左右位置

    titleEdgeInsets属性和 imageEdgeInsets属性只是在画这个button出来的时候用来调整image和label位置的属性,并不影响button本身的大小.它们只是image和 ...