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类型的物品.完成 所有发放后 ...
随机推荐
- day 82 Django Admin组件.
一.先建表环境 modules文件 from django.db import models # Create your models here. from django.contrib.auth.m ...
- dataframe.isnull()函数, DatetimeIndex,黄包车代码155行
待解决 feature 4 完全没懂 feature 5 219行: if (row.userid == action['userid'][row.max_index - 1]): ????
- Python 使用 os 模块遍历目录/获取当前文件的路径
1.列出指定目录下所包含的目录 item = os.listdir("/Users/jinchengxie/go") 返回的是一个列表, 里面包含了指定目录下所包含的所有的目录 2 ...
- php中strpos()函数
1,strpos()函数 mixed strops(]) 返回needle在haystack中首次出现的数字位置,从0开始查找,区分大小写. 参数:haystack,在该字符串中进行查找. needl ...
- SAX,功能强大的 API
https://www.ibm.com/developerworks/cn/xml/x-saxapi/ SAX,功能强大的 API 在摘自 XML by Example 的本篇预览中比较了 DOM 和 ...
- 【css】——三种方法实现多列等高
html: <section> <div class="item"> Lorem, ipsum dolor sit <div class=" ...
- python学习笔记06-enumerate()
enumerate() python 内置函数 枚举 列举的意思 对于一个可迭代的(iterable)/可遍历的对象(如列表.字符串),enumerate将其组成一个索引序列,利用它可以同时获得 ...
- iOS-AFNetworking参数和多文件同时上传【多文件上传】
1. 前言 在项目开发中,我们经常需要上传文件,例如:上传图片,上传各种文件,而有时也需要将参数和多个文件一起上传,不知道大家的项目中遇到了没有,我在最近的项目中,就需要这样的一个功能:同时上传参数. ...
- Java_使用日志
日志有什么用? 在实际开发中,不可能使用控制台输出所有数据,可以用日志把程序运行的过程记录下来,包括运行中出现的异常和BUG 当出现问题的时候,程序员可以去查看日志,从而能快速的找到问题所在. 一般来 ...
- Junit的常见注解
@Beforeclass:表示使用此注解的方法在测试类被调用之前执行,在一个测试类中只能声明此注解一次,此注解的方法只被执行一次 @AfterClass :表示使用此注解的方法在测试类被调用结束退出之 ...