HNCU专题训练_线段树(2)
1.统计颜色,或运算的运用
2.区间第k大数
3.一个很经典的题
5.求区间相等数字的个数
6.RMQ模板题,区间最大值和最小值的差
1.很好的思路,用或运算来避免左右儿子树总相同颜色的情况。由于
T颜色种类最多30种,__int64 足够用了。
注意初始化就行。
5.关键是写对make_up()这个函数,向上更新需要考虑的问题。经典题型。
1001
/* 求区间[l,r]中,颜色的总类。
如何避免重复?----或运算。 */ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define HH 1
using namespace std; struct node
{
int l;
int r;
int color;
__int64 num;
}f[*]; void build(int l,int r,int n)
{
int mid=(l+r)/;
f[n].l=l;
f[n].r=r;
f[n].color=;
f[n].num=<<;
if(l==r)
return ;
build(l,mid,n*);
build(mid+,r,n*+);
} void make_down(int n)
{
f[n*].color=f[n*+].color=HH; f[n*].num=f[n*+].num=f[n].num; f[n].color=;
f[n].num=;
} void update(int l,int r,int num,int n)
{
int mid=(f[n].l+f[n].r)/; if(f[n].l==l && f[n].r==r)
{
f[n].color=HH;
f[n].num=<<num;
return;
}
if(f[n].color==HH)
make_down(n);
if(mid>=r)
update(l,r,num,n*);
else if(mid<l)
update(l,r,num,n*+);
else
{
update(l,mid,num,n*);
update(mid+,r,num,n*+);
}
f[n].num=f[n*].num|f[n*+].num;
} __int64 query(int l,int r,int n)
{
int mid=(f[n].l+f[n].r)/;
__int64 cur=;
if(f[n].l==l && f[n].r==r)
{
return f[n].num;
}
if(f[n].color==HH)
make_down(n);
if(mid>=r)
cur=query(l,r,n*);
else if(mid<l)
cur=query(l,r,n*+);
else
{
cur=query(l,mid,n*)|query(mid+,r,n*+);
}
f[n].num=f[n*].num|f[n*+].num;
return cur; } int Get_num(__int64 num) //得到1的个数 很优化的算法。
{
int count=;
while(num)
{
++count;
num=(num-)#
}
return count;
} void make_ini(int L,int T,int O)
{
int A,B,num,hxl;
__int64 tmp;
char a[];
while(O--)
{
scanf("%s",a);
if(a[]=='C')
{
scanf("%d%d%d",&A,&B,&num);
if(A>B)
{
hxl=A;
A=B;
B=hxl;
}
if(num<=T)
update(A,B,num,);
}
else if(a[]=='P')
{
scanf("%d%d",&A,&B);
if(A>B)
{
hxl=A;
A=B;
B=hxl;
}
tmp=query(A,B,);
printf("%d\n",Get_num(tmp));
}
}
} int main()
{
int L,T,O;
while(scanf("%d%d%d",&L,&T,&O)>)
{
build(,L,);
make_ini(L,T,O);
}
return ;
}
1002
/*
第k小的数 */ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define NN 100010
using namespace std; int toleft[][NN];
int Tree[][NN];
int Sort[NN]; void build(int l,int r,int dep)
{
int mid=(l+r)/,sum=mid-l+,lpos,rpos,i;
if(l==r) return ;
for(i=l;i<=r;i++)
if(Tree[dep][i]<Sort[mid]) sum--;
lpos=l;
rpos=mid+;
for(i=l;i<=r;i++)
{
if(Tree[dep][i]<Sort[mid])
{
Tree[dep+][lpos++]=Tree[dep][i];
}
else if(Tree[dep][i]==Sort[mid] && sum>)
{
Tree[dep+][lpos++]=Tree[dep][i];
sum--;
}
else
{
Tree[dep+][rpos++]=Tree[dep][i];
}
toleft[dep][i]=toleft[dep][l-]+lpos-l;
}
build(l,mid,dep+);
build(mid+,r,dep+);
} int query(int L,int R,int l,int r,int k,int dep)
{
int mid=(L+R)/,newl,newr,cur;
if(l==r) return Tree[dep][l];
cur=toleft[dep][r]-toleft[dep][l-];
if(cur>=k)
{
newl=L+toleft[dep][l-]-toleft[dep][L-];
newr=newl+cur-;
return query(L,mid,newl,newr,k,dep+);
}
else
{
newr=r+(toleft[dep][R]-toleft[dep][r]);
newl=newr-(r-l-cur);
return query(mid+,R,newl,newr,k-cur,dep+);
}
} void make_ini(int N,int M)
{
int l,r,k;
while(M--)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",query(,N,l,r,k,));
}
} int main()
{
int N,M,i;
while(scanf("%d%d",&N,&M)>)
{
for(i=;i<=N;i++)
{
scanf("%d",&Tree[][i]);
Sort[i]=Tree[][i];
}
sort(Sort+,Sort++N);
build(,N,);
make_ini(N,M);
}
return ;
}
1003
#include<cstdio>
#include<iostream>
#include<cstdlib>
#define HH 1 //纯色
using namespace std; struct st
{
__int64 l;
__int64 r;
__int64 num;
__int64 color;
__int64 max;
}f[*];
__int64 date[]; void build(__int64 l,__int64 r,__int64 n)
{
__int64 mid=(l+r)/;
f[n].l=l;
f[n].r=r;
f[n].color=;
f[n].num=;
if(l==r)
{
f[n].max=date[l];
return;
}
build(l,mid,n*);
build(mid+,r,n*+);
f[n].max=f[n*].max+f[n*+].max;
} void make_down(__int64 n)
{ f[n*].num+=f[n].num;
f[n*].color=HH;
f[n*].max+=f[n].num*(f[n*].r-f[n*].l+); f[n*+].num+=f[n].num;
f[n*+].color=HH;
f[n*+].max+=f[n].num*(f[n*+].r-f[n*+].l+); f[n].color=;f[n].num=;
} void update(__int64 l,__int64 r,__int64 num,__int64 n)
{
__int64 mid=(f[n].l+f[n].r)/;
if(f[n].l==l && f[n].r==r)
{
f[n].num+=num;
f[n].max+=num*(f[n].r-f[n].l+);
f[n].color=HH;
return ;
}
if(f[n].color==HH)
make_down(n);
if(mid>=r)
update(l,r,num,n*);
else if(mid<l)
update(l,r,num,n*+);
else
{
update(l,mid,num,n*);
update(mid+,r,num,n*+);
}
f[n].max=f[n*].max+f[n*+].max;
} __int64 query(__int64 l,__int64 r,__int64 n)
{
__int64 mid=(f[n].l+f[n].r)/;
__int64 cur=;
if(f[n].l==l && f[n].r==r)
{
return f[n].max;
}
if(f[n].color==HH)
make_down(n);
if(mid>=r)
cur= query(l,r,n*);
else if(mid<l)
cur= query(l,r,n*+);
else
{
cur+= query(l,mid,n*);
cur+=query(mid+,r,n*+);
}
f[n].max=f[n*].max+f[n*+].max;
return cur;
} int main()
{
__int64 n,q,i,l,r,num;
char a[];
while(scanf("%I64d%I64d",&n,&q)>)
{
for(i=;i<=n;i++)
scanf("%I64d",&date[i]);
build(,n,);
while(q--)
{
scanf("%s",a);
if(a[]=='Q')
{
scanf("%I64d%I64d",&l,&r);
printf("%I64d\n",query(l,r,));
}
else if(a[]=='C')
{
scanf("%I64d%I64d%I64d",&l,&r,&num);
update(l,r,num,);
}
}
}
return ;
}
1005
/* 求区间[l,r]中,相等数字的最大个数
试一试能不能A。 */ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std; struct node
{
int l;
int r;
int lmax,rmax,max;
int lnum,rnum;
int len;
}f[*];
int Date[]; int hmax(int x,int y)
{
return x>y? x: y;
} int hmin(int x,int y)
{
return x>y? y:x;
} void make_up(node *father,node *l_child,node *r_child)
{
father->lnum=l_child->lnum;
father->rnum=r_child->rnum;
if(l_child->rnum!=r_child->lnum)
{
father->lmax=l_child->lmax;
father->rmax=r_child->rmax;
father->max=hmax(hmax(father->lmax,father->rmax),
hmax(l_child->max,r_child->max));
}
else
{
father->lmax=(l_child->lmax==l_child->len)? l_child->lmax+r_child->lmax:l_child->lmax;
father->rmax=(r_child->rmax==r_child->len)? r_child->rmax+l_child->rmax:r_child->rmax;
father->max= hmax(hmax(father->lmax,father->rmax),
hmax(l_child->max,
hmax(r_child->max,l_child->rmax+r_child->lmax)));
}
} void build(int l,int r,int n)
{
int mid=(l+r)/;
f[n].l=l;
f[n].r=r;
f[n].len=f[n].r-f[n].l+;
if(l==r)
{
f[n].lnum=Date[l];
f[n].rnum=Date[l];
f[n].lmax=f[n].rmax=f[n].max=;
return ;
}
build(l,mid,n*);
build(mid+,r,n*+);
make_up(&f[n],&f[n*],&f[n*+]);
} int query(int l,int r,int n)
{
int mid=(f[n].l+f[n].r)/,cur=,now1=,now2=; if(f[n].l==l && f[n].r==r)
{
return f[n].max;
}
if(mid>=r)
cur=query(l,r,n*);
else if(mid<l)
cur=query(l,r,n*+);
else
{
now1=query(l,mid,n*);
now2=query(mid+,r,n*+);
if(f[n*].rnum==f[n*+].lnum)
{
cur=hmax(hmax(now1,now2),hmin(mid-l+,f[n*].rmax)+
hmin(r-mid,f[n*+].lmax));
}
else
{
cur=hmax(now1,now2);
}
}
return cur;
} void make_ini(int Q)
{
int l,r;
while(Q--)
{
scanf("%d%d",&l,&r);
printf("%d\n",query(l,r,));
}
} int main()
{
int N,Q,i;
while(scanf("%d",&N)>)
{
if(N==)break;
scanf("%d",&Q);
for(i=;i<=N;i++)
scanf("%d",&Date[i]);
build(,N,);
make_ini(Q);
}
}
1006
/*
求区间[l,r],最大值和最小值的差值。
*/ #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define MAX 1000010
using namespace std; struct node
{
int l;
int r;
int min;
int max;
}f[*];
int Date[]; int hmax(int x,int y)
{
return x>y? x:y;
} int hmin(int x,int y)
{
return x>y? y:x;
} void build(int l,int r,int n)
{
int mid=(l+r)/;
f[n].l=l;
f[n].r=r;
if(l==r)
{
f[n].max=Date[l];
f[n].min=Date[l];
return;
}
build(l,mid,n*);
build(mid+,r,n*+);
f[n].max=hmax(f[n*].max,f[n*+].max);
f[n].min=hmin(f[n*].min,f[n*+].min);
} void query(int l,int r,int *a,int *b,int n)
{
int mid=(f[n].l+f[n].r)/;
if(f[n].l==l && f[n].r==r)
{
if(f[n].min<*a)
*a=f[n].min;
if(f[n].max>*b)
*b=f[n].max;
return;
}
if(mid>=r)
query(l,r,a,b,n*);
else if(mid<l)
query(l,r,a,b,n*+);
else
{
query(l,mid,a,b,n*);
query(mid+,r,a,b,n*+);
}
} int main()
{
int N,Q,i;
int a,b,l,r;
while(scanf("%d%d",&N,&Q)>)
{
for(i=;i<=N;i++)
scanf("%d",&Date[i]);
build(,N,);
while(Q--)
{
scanf("%d%d",&l,&r);
a=MAX;b=-;
query(l,r,&a,&b,);
printf("%d\n",b-a);
}
}
return ;
}
HNCU专题训练_线段树(2)的更多相关文章
- HNCU专题训练_线段树(1)
1.内存控制2.敌兵布阵4.广告牌5.区间第k大数(模板题)6.just a Hook7.I Hate It8.动态的最长递增子序列(区间更新题)9.图灵树10.覆盖的面积14.买票问题16.村庄问题 ...
- BZOJ_4636_蒟蒻的数列_线段树+动态开点
BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...
- BZOJ_3252_攻略_线段树+dfs序
BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...
- BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针
BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...
- BZOJ_2124_等差子序列_线段树+Hash
BZOJ_2124_等差子序列_线段树+Hash Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pL ...
- BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心
BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...
- BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树
BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树 Description Input 第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数 ...
- BZOJ_1798_[AHOI2009]维护序列_线段树
BZOJ_1798_[AHOI2009]维护序列_线段树 题意:老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: ( ...
- BZOJ_3307_雨天的尾巴_线段树合并+树上差分
BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...
随机推荐
- Linux下运行crm项目
虚拟环境运行crm项目 1.进入虚拟环境 2.解决crm项目运行所需的依赖环境 1.手动解决 pip3 install django==1.11.14 pip3 install pymysql pip ...
- Mac OS 10.12 - 如何能够像在Windows一样切换中英文输入法和大小写键?
最开始,我切换中英文输入法和大小写键是按照下面博客做到的: http://www.cnblogs.com/sunylat/p/6415563.html 但是当我安装完毕搜狗输入法后,切换中英文输入法和 ...
- MySQL(安装,服务,创建用户及授权)
参考:http://www.cnblogs.com/wupeiqi/p/5713315.html 单机程序(自己DB) 单机程序(公用DB) MySQL:是用于管理文件的一 ...
- linux下tomcat运行war包常用命令
一.先是war包copy到 linux 的相关目录,我这的是/opt/soft/tomcat_ecp/webapps. 如果是老项目,在导入war的之前,习惯上是把之前的war备份一下, 如 mv p ...
- Ubuntu“无法打开锁文件(Could not get lock)”问题解决
用apt-get安装软件时提示: 无法获得锁 /var/lib/dpkg/lock - open(11:资源暂时不可用) 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它? 其 ...
- 【转】Unity Animator卡顿研究
Unity Animator卡顿研究 发表于2017-07-26 点赞3 评论3 分享 分享到 2.3k浏览 想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏程序行业精英群 ...
- Mac 10.12连接iSCSI硬盘软件iSCSI Initiator X
Mac下的iSCSI协议苹果一直以来没有集成,而网络上流传的最好用支持iSCSI硬盘的软件是globalSAN,但是这个软件是收费的,当然有破解版,只不多不太好找,因为现在用iSCSI的用户已经很少了 ...
- Django中url的反向查询
明确几个概念: application namespace: 正在部署的app的名称,一个app的多个实例应该具有相同的application namespace. 可以通过在URLconf模 ...
- (转)MySQL详解--锁
原文:http://blog.csdn.net/xifeijian/article/details/20313977 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源( ...
- 2018春招-今日头条笔试题-第二题(python)
题目描述:2018春招-今日头条笔试题5题(后附大佬答案-c++版) 解题思路: 利用深度优先搜索 #-*- coding:utf-8 -*- class DFS: ''' num:用于存储最后执行次 ...