物理( 线段树套单调队列 )
来源:互联网 发布:淘宝客服中心怎么装修 编辑:程序博客网 时间:2024/05/16 15:07
sg站在1号点,后面有他的n-1个小弟。现在妹子想告诉sg一些话,但是她不知道选谁。由于sg的小弟们构造奇特,他们能听到的声波频率也是不一样的。第i个人可以发出并接收声波频率为[xi,yi]的声音,并且每个人的声音最多只能传播不超过l的距离。每一次说话并被另一个人接收到的过程都要消耗1单位时间。
现在给出所有人能发出并接收的声波频率的范围和位置,sg的妹子想知道,每个小弟传话给sg要多久。由于sg很牛逼,他可以接收所有小弟发出的声波,当然前提要在距离之内。sg的位置为0。
Input
第一行:n,l,含义见题意。
第二行至第n行:xi,yi,li,[xi,yi]是第i个小弟能发出并接收的声波频率范围,li是第i个小弟的位置。
Output
第一行至第n-1行:第i行表示第i+1个小弟要传话给sg所消耗的时间。
对于暴力
然后我们考虑维护min的部分;
考虑开一个线段树,以频率为下标。
然后呢? 怎么解决长度问题?总不可能在线段树每个节点塞一个线性表每次遍历扫一遍
显然
怎么维护这个线段树呢?
每个节点开两个单调队列,cover[] && pass[]
对于Insert操作,每经过一个节点更新一下pass[],遇到整段配对的区间更新cover[]
对于Ask操作,每经过一个节点用cover[]来更新遇到整段配对的区间更新pass[],
时间虽然给了5s仍然有点紧,有些小优化,如
cover被更新的节点不用更新pass
不要用map离散化数据
只在Ask操作内删除队首非法节点
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<map>using namespace std ;#define N 250010#define psb( x ) push_back( x ) int i , j , k , n , L ;map< int , int > s ;struct node { int x , y , l , ps ;}z[N] ;// We Store id struct SegmentTree_With_Queue { vector<int> cover , pass ; int cl , cr , pl , pr ; // Remember to Initialize }tr[N*2*4] ;int f[N] , demap[N*2] ;struct For_Dis { int ps , va ; bool x ;}a[N*2] ;bool cmp( For_Dis a , For_Dis b ) { return a.va < b.va ;}bool _cmp( node a , node b ) { return a.l < b.l ;}void Ins( int _l , int _r , int l , int r , int va , int po ) { int m = l+r >> 1 ; if( _l==l && _r==r ) { while( tr[po].cl<=tr[po].cr && f[ tr[po].cover[ tr[po].cr ] ] > f[va] ) tr[po].cr-- ; if( ( tr[po].cr + 1 ) >= tr[po].cover.size() ) tr[po].cover.psb( 0 ); tr[po].cover[ ++tr[po].cr ] = va ; return ; } while( tr[po].pl<=tr[po].pr && f[ tr[po].pass[ tr[po].pr ] ] > f[va] ) tr[po].pr -- ; if( ( tr[po].pr+1 ) >= tr[po].pass.size() ) tr[po].pass.psb( 0 ) ; tr[po].pass[ ++tr[po].pr ] = va ; if( _r<=m ) Ins( _l,_r,l,m,va,po*2 ) ; else if( _l>m ) Ins( _l,_r,m+1,r,va,po*2+1 ) ; else Ins( _l,m,l,m,va,po*2 ) , Ins( m+1,_r,m+1,r,va,po*2+1 );}int cur , ax = 0 ;void Ask( int _l , int _r , int l , int r , int po ) { int m = l + r >> 1 ; while( tr[po].cl<=tr[po].cr && -z[ tr[po].cover[ tr[po].cl ] ].l + z[ cur ].l > L ) tr[po].cl ++ ; if( tr[po].cl <= tr[po].cr ) if( ax==-1 || f[ax]>f[ tr[po].cover[ tr[po].cl ] ] ) ax = tr[po].cover[ tr[po].cl ] ; if( l==_l && r==_r ) { while( tr[po].pl<=tr[po].pr && -z[ tr[po].pass[ tr[po].pl ] ].l + z[ cur ].l > L ) tr[po].pl ++ ; if( tr[po].pl <= tr[po].pr ) if( ax==-1 || f[ax]>f[ tr[po].pass[ tr[po].pl ] ] ) ax = tr[po].pass[ tr[po].pl ] ; return ; } if( _r<=m ) Ask( _l , _r , l , m , po * 2 ) ; else if( _l>m ) Ask( _l , _r , m+1 , r , po * 2 + 1 ) ; else Ask( _l , m , l , m , po * 2 ) , Ask( m+1 , _r , m+1 , r , po * 2 + 1 ) ;}void BuildTree( int l , int r , int po ) { tr[po].cl = tr[po].pl = 1 , tr[po].cr = tr[po].pr = 0 ; tr[po].cover.psb( 0 ) , tr[po].pass.psb( 0 ) ; tr[po].cover.psb( 0 ) , tr[po].pass.psb( 0 ) ; if( l==r ) return ; BuildTree( l , l + r >> 1 , po << 1 ) ; BuildTree( ( r + l >> 1 ) + 1 , r , ( po << 1 ) + 1 ) ;}int ans[N] ;int main() { scanf("%d%d",&n,&L ) ; --n ; for( i=1 ; i<=n ; i++ ) { scanf("%d%d%d",&z[i].x,&z[i].y,&z[i].l ) ; a[i*2-1].va = z[i].x ; a[i*2].va = z[i].y ; a[i*2-1].ps = a[i*2].ps = i ; a[i*2-1].x = 1 ; z[i].ps = i ; } sort( a+1 , a+1+n*2 , cmp ) ; int disva = 0 ; a[0].va = -1 ; for( i=1 ; i<=n*2 ; i++ ) { if( a[i].va!=a[i-1].va ) ++ disva ; if( a[i].x ) z[ a[i].ps ].x = disva ; else z[ a[i].ps ].y = disva ; } sort( z+1 , z+1+n , _cmp ) ; BuildTree( 1 , disva , 1 ) ; tr[1].cover.psb( 0 ) ; tr[1].cl = tr[1].cr = 1 ; f[0] = 0 ; for( i=1 ; i<=n ; i++ ) { cur = i ; ax = -1 ; Ask( z[i].x , z[i].y , 1 , disva , 1 ) ; if( ax == -1 ) { ans[ z[i].ps ] = -1 ; continue ; } f[i] = f[ax] + 1 ; Ins( z[i].x , z[i].y , 1 , disva , i , 1 ) ; ans[ z[i].ps ] = f[i] ; } for( i=1 ; i<=n ; i++ ) printf("%d\n",ans[i] ) ;}
DebugLogo
1 删队首不等式符号恰好写反
2 更新区间最小值判断语句符号写反
写比较长的布尔式要慢点写,图快反而得不偿失。
- 物理( 线段树套单调队列 )
- bzoj1012(线段树或单调队列)
- XDU-1156 等待队列 (线段树||单调队列)
- poj 2823 Sliding Window (单调队列 or 线段树)
- POJ 2823 Sliding Window(单调队列||线段树)
- [caioj] 问题 E: 单调队列3 (线段树)
- pku 2823(单调队列、线段树)
- POJ2823:Sliding Window(单调队列||线段树)
- POJ2823 线段树OR单调队列
- 线段树和单调队列优化DP
- poj2823--Sliding Window--线段树||单调队列
- BZOJ 1012 线段树||单调队列
- 【bzoj4262】Sum 线段树+单调队列
- hdu 4122 单调队列或线段树
- POJ 2823 线段树 Or 单调队列
- bzoj 1012 最大数(线段树|单调队列|单调栈)
- NKOJ 4000 (AHOI 2013)差异(后缀自动机/后缀数组+线段树/单调队列)
- Light OJ 1084 线段树+dp or(单调队列+dp) 水题
- Android TextView 横向滚动(跑马灯效果)
- 今天给大家说说使用Jenkins专有用户数据库的配置,和一些常用的权限配置。
- 查找输入整数二进制中1的个数
- 配置使用Android数据库开源框架GreenDao
- CF#310 div2 D set+pair+贪心
- 物理( 线段树套单调队列 )
- 征服 Redis + Jedis
- cocos2dx导入到eclipse出现"C/C++ Indexer". java.lang.NullPointerException
- Redis应用场景
- HDOJ 1379 DNA Sorting (sort 快排)
- ADB server didn't ACK
- mysql 查找不存在的id
- 使用ssh公钥实现面密码登录:RSA公钥
- CSS中的盒模型