Mango DS Training #48 ---线段树2 解题手记
Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38966#overview
A.Count Color --- POJ 2777
这题初看不好下手,再想想,T<=30,这时想到颜色可以用二进制来表示,然后父节点颜色种类为子节点的按位或得出的结果中化为二进制时1的个数,然后就是无脑线段树了。。
代码:
#include <iostream>
#include <cstdio>
#include <utility>
#include <cstdlib>
using namespace std;
#define N 100010 struct node
{
int mark;
int sum;
}tree[*N]; void pushup(int rt)
{
tree[rt].sum = tree[*rt].sum | tree[*rt+].sum;
} void build(int l,int r,int rt)
{
tree[rt].sum = ;
tree[rt].mark = ;
if(l == r)
return;
int mid = (l+r)/;
build(l,mid,*rt);
build(mid+,r,*rt+);
pushup(rt);
} void pushdown(int l,int r,int rt)
{
if(!tree[rt].mark)
return;
if(tree[rt].mark)
{
tree[*rt].sum = tree[*rt+].sum = tree[rt].sum;
tree[*rt].mark = tree[*rt+].mark = tree[rt].mark;
tree[rt].mark = ;
}
} void make(int l,int r,int aa,int bb,int co,int rt)
{
if(aa<=l && bb>=r)
{
tree[rt].mark = ;
tree[rt].sum = <<(co-);
return;
}
pushdown(l,r,rt);
int mid = (l+r)/;
if(aa<=mid)
make(l,mid,aa,bb,co,*rt);
if(bb>mid)
make(mid+,r,aa,bb,co,*rt+);
pushup(rt);
} int query(int l,int r,int aa,int bb,int rt)
{
if(aa>r||bb<l)
return ;
if(aa<=l&&bb>=r)
{
return tree[rt].sum;
}
pushdown(l,r,rt);
int mid = (l+r)/;
return query(l,mid,aa,bb,*rt)|query(mid+,r,aa,bb,*rt+);
} int main()
{
int n,t,o;
int i;
int aa,bb,co;
char ss[];
scanf("%d%d%d",&n,&t,&o);
build(,n,);
int cnt;
for(i=;i<o;i++)
{
scanf("%s",ss);
if(ss[] == 'C')
{
scanf("%d%d%d",&aa,&bb,&co);
make(,n,aa,bb,co,);
}
else if(ss[] == 'P')
{
scanf("%d%d",&aa,&bb);
int res;
if(aa<=bb)
res = query(,n,aa,bb,);
else
res = query(,n,bb,aa,);
cnt = ;
while(res)
{
if(res&)
cnt++;
res>>=;
}
printf("%d\n",cnt);
}
}
return ;
}
B.Who Gets the Most Candies --- POJ 2886
(题解借鉴: ahfywff)
本题利用反素数的概念。反素数的定义:对于任何正整数x,其约数的个数记做f(x)。例如f(1)=1,f(6)=4。如果某个正整数x满足:对于任意i(0<i<x),都有f(i)<f(x),则称x为反素数。对于本题,设pos为不大于N的反素数,则第pos个出圈的孩子得到的糖果最多,为pos的约数个数。
出圈过程有点类似约瑟夫环。假设当前出圈的是剩余孩子中的第K个,他手中的数字为A。
若A大于零,下一个出圈的就应该是剩余孩子中的第(K-1+A-1)%n+1个;
若A小于零,下一个出圈的就应该是剩余孩子中的第((K-1+A)%n+n)%n+1个。
问题的关键是如何求得出圈孩子的原始位置,线段树的每个节点的sum存储了所在区间还有多少孩子留下,查询节点rt中第num个孩子的原始位置时,如果num<=st[2*rt].sum,则在左孩子节点中查询第num个孩子的原始位置;否则在右孩子节点中查询第num-st[2*rt].sum个孩子的原始位置。
代码:
/*12152 KB 1079 ms*/
#include <iostream>
#include <cstdio>
using namespace std;
#define N 500010 int anti[]={,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,};
int factor[]={,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,}; int tree[*N];
char name[N][];
int num[N]; void build(int l,int r,int rt)
{
tree[rt] = r-l+;
if(l == r)
return;
int mid = (l+r)/;
build(l,mid,*rt);
build(mid+,r,*rt+);
} int query(int l,int r,int pos,int rt)
{
tree[rt]--;
if(l == r)
return l;
int mid = (l+r)/;
if(pos<=tree[*rt])
return query(l,mid,pos,*rt);
else
return query(mid+,r,pos-tree[*rt],*rt+);
} int main()
{
int n,k,pos,Maxcandy,i;
while(scanf("%d%d",&n,&k)!=EOF)
{
i=;
int CN = n;
while(anti[i]<=n)
i++;
pos = anti[i-];
Maxcandy = factor[i-];
build(,n,);
for(i=;i<=n;i++)
{
scanf("%s %d",name[i],&num[i]);
}
int flag;
for(i=;i<=pos;i++)
{
n--;
flag = query(,CN,k,);
if(n==)
break;
if(num[flag]>)
k = (k + num[flag] - )%n + ;
else
k = ((k + num[flag] - )%n+n)%n + ;
}
printf("%s %d\n",name[flag],Maxcandy);
}
}
G.Fast Matrix Operations ---UVA 11992
这题其实也不太难搞,关键是各方面要维护到,我写了两个多小时啊,最后还是有些地方没有照顾到,哎,太弱咯。。感觉自己在维护值方面还差一点火候。 这题看行数不超过20,想到在每一行都建一颗线段树,然后就搞吧。。代码有点长,将就着看吧。
(A.M : Attention to Maintain)
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <utility>
#include <cstdlib>
#define Mod 1000000007
using namespace std;
#define N 1000010 struct node
{
int mini,maxi,sum;
int addmark,setmark;
}tree[][*N]; int i; void pushup(int i,int rt)
{
tree[i][rt].sum = tree[i][*rt].sum + tree[i][*rt+].sum;
tree[i][rt].mini = min(tree[i][*rt].mini,tree[i][*rt+].mini);
tree[i][rt].maxi = max(tree[i][*rt].maxi,tree[i][*rt+].maxi);
} void build(int i,int l,int r,int rt)
{
tree[i][rt].sum = tree[i][rt].mini = tree[i][rt].maxi = ;
tree[i][rt].setmark = -;
tree[i][rt].addmark = ;
if(l == r)
return;
int mid = (l+r)/;
build(i,l,mid,*rt);
build(i,mid+,r,*rt+);
pushup(i,rt);
} void pushdown(int i,int l,int r,int rt)
{
if(tree[i][rt].setmark == - && tree[i][rt].addmark == )
return;
int mid = (l+r)/;
if(tree[i][rt].setmark >= )
{
tree[i][*rt].sum = tree[i][rt].setmark*(mid-l+);
tree[i][*rt+].sum = tree[i][rt].setmark*(r-mid);
tree[i][*rt].mini = tree[i][*rt+].mini = tree[i][rt].setmark; //A.M
tree[i][*rt].maxi = tree[i][*rt+].maxi = tree[i][rt].setmark; //A.M
tree[i][*rt].addmark = tree[i][*rt+].addmark = ; // 这个要写
tree[i][*rt].setmark = tree[i][*rt+].setmark = tree[i][rt].setmark;
tree[i][rt].setmark = -;
}
if(tree[i][rt].addmark > )
{
tree[i][*rt].sum += tree[i][rt].addmark*(mid-l+);
tree[i][*rt+].sum += tree[i][rt].addmark*(r-mid);
tree[i][*rt].maxi += tree[i][rt].addmark; //A.M
tree[i][*rt].mini += tree[i][rt].addmark; //A.M
tree[i][*rt+].maxi += tree[i][rt].addmark; //A.M
tree[i][*rt+].mini += tree[i][rt].addmark; //A.M
tree[i][*rt].addmark += tree[i][rt].addmark;
tree[i][*rt+].addmark += tree[i][rt].addmark;
tree[i][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[i][rt].addmark += val;
//tree[i][rt].setmark = -1; --不要写这个
tree[i][rt].sum += (r-l+)*val;
tree[i][rt].maxi += val;
tree[i][rt].mini += val;
return;
}
pushdown(i,l,r,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(i,rt);
} void setval(int l,int r,int aa,int bb,int val,int rt)
{
if(aa>r||bb<l)
return;
if(aa<=l&&bb>=r)
{
tree[i][rt].setmark = val;
tree[i][rt].addmark = ;
tree[i][rt].sum = val*(r-l+);
tree[i][rt].maxi = tree[i][rt].mini = val;
return;
}
pushdown(i,l,r,rt);
int mid = (l+r)/;
if(aa<=mid)
setval(l,mid,aa,bb,val,*rt);
if(bb>mid)
setval(mid+,r,aa,bb,val,*rt+);
pushup(i,rt);
} struct node_ans
{
int sum;
int mini,maxi;
}; node_ans query(int l,int r,int aa,int bb,int rt)
{
node_ans res,ka1,ka2;
if(aa<=l && bb>=r)
{
res.sum = tree[i][rt].sum;
res.maxi = tree[i][rt].maxi;
res.mini = tree[i][rt].mini;
return res;
}
pushdown(i,l,r,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
{
ka1 = query(l,mid,aa,bb,*rt);
ka2 = query(mid+,r,aa,bb,*rt+);
res.sum = ka1.sum + ka2.sum;
res.maxi = max(ka1.maxi,ka2.maxi);
res.mini = min(ka1.mini,ka2.mini);
return res;
}
} int main()
{
int r,c,m;
int k,zuo;
int x1,y1,x2,y2,val;
int sum,mmax,mmin;
while(scanf("%d%d%d",&r,&c,&m)!=EOF)
{
for(i=;i<=r;i++)
{
build(i,,c,);
}
for(k=;k<m;k++)
{
scanf("%d",&zuo);
if(zuo == )
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
for(i=x1;i<=x2;i++)
{
add(,c,y1,y2,val,);
}
}
else if(zuo == )
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
for(i=x1;i<=x2;i++)
{
setval(,c,y1,y2,val,);
}
}
else
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
node_ans la;
sum = ;
mmax = -Mod;
mmin = Mod;
for(i=x1;i<=x2;i++)
{
la = query(,c,y1,y2,);
sum += la.sum;
mmax = max(mmax,la.maxi);
mmin = min(mmin,la.mini);
}
printf("%d %d %d\n",sum,mmin,mmax);
}
}
}
}
Mango DS Training #48 ---线段树2 解题手记的更多相关文章
- Mango DS Traning #49 ---线段树3 解题手记
Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38994#overview B.Xenia and B ...
- 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.求出某区间每一个数的和 输入输出格式 ...
- uestc summer training #3 线段树优化建边
线段树建边 struct E { int value, modvalue; } a[MAXN << ]; pair<int, int> b[MAXN]; ], r[MAXN & ...
- 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/ ...
随机推荐
- 由简入繁实现Jquery树状结构
在项目中,我们经常会需要一些树状结构的样式来显示层级结构等,比如下图的样式,之前在学.net的时候可以直接拖个服务端控件过来直接使用非常方便.但是利用Jquery的一些插件,也是可以实现这些效果的,比 ...
- Ahjesus Nodejs02 使用集成开发环境
下载最新版webstorm, 选择此集成开发环境是因为支持性较好,在vs下也有插件支持,不过感觉有些牵强 附vs插件 NTVS 详细介绍 安装好以后就需要配置npm NPM 国内高速镜像 source ...
- 快速设置超炫banner,js插件
http://www.themepunch.com/codecanyon/revolution_wp/ 记录一下以后用 //出自http://www.cnblogs.com/ahjesus 尊重作者辛 ...
- guacamole 0.9.9安装与配置
以下命令很多都需要管理权限,建议使用管理员账号执行,遇到问题可以留言. 1.首先需要安装guacamole所需要的依赖库 必需安装的库有:Cairo.libjpeg-turbo.libpng.OSSP ...
- (三)play之yabe项目【数据模型】
(三)play之yabe项目[数据模型] 博客分类: 框架@play framework 创建项目 play new yabe What is the application name? [yab ...
- The URL "filename" is invalid. It may refer to a nonexistent file or folder, or refer to a valid file or folder that is not in the current Web
Sharepoint Error : The URL "filename" is invalid. It may refer to a nonexistent file or fo ...
- 2015年第5本(英文第4本):Death on the Nile尼罗河上的惨案
书名:Death on the Nile 作者: Agatha Christie 单词数:7.9万(读完后发现网上还有一个版本,总共2.7万单词,孩子都能读懂,看来是简写版) 词汇量:6700 首万词 ...
- 【读书笔记】iOS-内存管理
Cocoa的内存管理:retain,release和autorelease. 每个对象都维护一个保留计数器.对象被创建时,其保留计数器值为1:对象被保留时,保留计数器值加1:对象被释放时,保留计数器值 ...
- sql 存储过程中top 后面跟参数的问题
之前存储过程中有top的情况,都是拼接sql,然后通过exec执行,进行查询结果,很不方便. 今天研究了,原来top后面是可以直接写参数的. 只需要top 后面的参数加上小括号就好了 eg: TOP ...
- Android Design Support Library——Floating Action Button
Floating Action Button是一种悬浮操作的圆形按钮,继承自ImageView,可以通过android:src或者ImageView的任意方法,来设置FloatingActionBut ...