首页 > 其他分享 >bzoj 2006 [NOI2010] 超级钢琴 线段树求区间极值+优先队列

bzoj 2006 [NOI2010] 超级钢琴 线段树求区间极值+优先队列

时间:2023-03-24 09:58:57浏览次数:47  
标签:rt return idx int sum 树求 2006 NOI2010 id

挺神奇的一道题,唯一想不通的是为什么放在主席树的题单里..

首先暴力找出所有的合法区间显然是不可能的。

考虑怎么贪心,假如固定每个L作为左端点,那么合法的区间就是[L+l-1,L+r-1](当然还要跟n取个min)

对于每个L,用线段树求出合法区间内最大的值,以及取得最大值时所对应的点,设为idx

然后我们维护一个堆,把这些区间都丢进去,算答案时取最大的。

然后呢?第二大呢?

显然对于第一轮没有被选到的区间,不需要考虑它们是否会产生新的最大

那么答案就呼之欲出啦,可能产生第二大的就是被选中的区间内其他的点

我们把被选中的区间[L+l-1,L+r-1]分裂成 [L+l-1,idx-1] 和 [idx+1,L+r-1];

然后再丢进去,做K次:D

 

 

 

#include<bits/stdc++.h>
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ls (rt<<1)
#define rs (rt<<1|1)
using namespace std;
const int maxn=5e5+5;
int n,k,l,r,a[maxn],sum[maxn];
struct tree{
    int mx,idx;
}t[maxn<<2];
void push_up(int rt){
    if(t[ls].mx>=t[rs].mx){
        t[rt]=t[ls];
    }
    else t[rt]=t[rs];
}
void build(int rt,int l=1,int r=n){
    if(l==r){
        t[rt].mx=sum[l];
        t[rt].idx=l;
        return;
    }
    int mid=l+r>>1;
    build(ls,l,mid);build(rs,mid+1,r);
    push_up(rt);
}
int query(int ql,int qr,int rt=1,int l=1,int r=n){
    if(ql<=l&&r<=qr){
        return t[rt].idx;
    }
    int mid=l+r>>1;
    int ans1=0,ans2=0;
    if(ql<=mid) ans1=query(ql,qr,ls,l,mid);
    if(qr>mid) ans2=query(ql,qr,rs,mid+1,r);
    if(!ans1) return ans2;
    else if(!ans2) return ans1;
    else if(sum[ans1]>=sum[ans2]) return ans1;
    else return ans2;
}
struct point{
    int l,r,val,id,L;
    bool operator > (const point a) const{
       return val<a.val;
    }
};
priority_queue<point,vector<point>,greater<point>>q;
int main(){
    //freopen("lys.in","r",stdin);
    fastio;
    cin>>n>>k>>l>>r;
    for(int i=1;i<=n;i++) {
       cin>>a[i],sum[i]=sum[i-1]+a[i];
    }
    build(1);
    for(int i=1;i<=n;i++){
        int lef=i+l-1,rig=i+r-1;
        rig=min(rig,n);lef=min(lef,n);
        if(lef-i+1<l) continue;
        int idx=query(lef,rig);
        //cout<<"id: "<<i<<" "<<lef<<" "<<rig<<" "<<idx<<endl;
        q.push((point){lef,rig,sum[idx]-sum[i-1],idx,i});
    }
    //cout<<"finished"<<endl;
    long long tot=0;
    int cnt=k;
    while(cnt--){
        point Top=q.top();
        q.pop();
        tot=tot+Top.val;
        int idx=Top.id,lef=Top.l,rig=Top.r,L=Top.L;
        //cout<<"add: "<<idx<<" "<<lef<<" "<<rig<<" "<<Top.val<<" "<<L<<endl;
        if(idx>lef){
            if(lef-L+1>=l){
               int id=query(lef,idx-1);
               q.push((point){lef,idx-1,sum[id]-sum[L-1],id,L});    
            }
        }
        if(idx<rig){
            if(idx+1-L+1>=l){
               int id=query(idx+1,rig);
               q.push((point){idx+1,rig,sum[id]-sum[L-1],id,L});    
            }
        } 
    }
    cout<<tot<<endl;
}

 

标签:rt,return,idx,int,sum,树求,2006,NOI2010,id
From: https://www.cnblogs.com/liyishui2003/p/17250358.html

相关文章

  • 【题解】[Ynoi2010] y-fast trie
    题目分析:显然可以对于所有的\(x\)对\(C\)取模后处理。那么就是两种情况:\(x+y\geC\)\(x+y<C\)对于第一种情况直接找最大的两个数就好了,关键就是第二种情......
  • P3205 [HNOI2010]合唱队(区间dp+方案数)
    P3205[HNOI2010]合唱队-洛谷|计算机科学教育新生态(luogu.com.cn)这道题大区间包括小区间,每加一个人都会让区间更大;考虑区间DP:对于区间[i~j],这段区间最新......
  • go 神奇的错误 time.Now().Format("2006-01-02 13:04:05") 比北京时间大8小时
    困倦的时候写了个个获取本地时间,打印总比当前时间大8小时,找了很久原因 packagemainimport("fmt""time")funcmain(){now:=time.Now()f......
  • HDOJ2006求奇数的乘积
    求奇数的乘积TimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/32768K(Java/Others)TotalSubmission(s):103371    AcceptedSubmission(s):......
  • Educational Codeforces Round 102 (Rated for Div. 2)D(线段树求贡献)
    EducationalCodeforcesRound102(RatedforDiv.2)D(线段树求贡献)D.Program题目大意:最初x为0,给定一个长度为n的操作序列,共有两种操作:-,x-=1;+,x+=1;有m次询......
  • B2006 地球人口承载力估计--解题思路
    地球人口承载力估计地球人口承载力估计题目描述假设地球上的新生资源按恒定速度增长。照此测算,地球上现有资源加上新生资源可供\(x\)亿人生活\(a\)年,或供\(y\)亿......
  • 【NOIP2006】【codevs1075】明明的随机数
    problemsolutioncodes#include<iostream>usingnamespacestd;intn,a[1010],t;intmain(){cin>>n;for(inti=1;i<=n;i++){intx;cin>>x;......
  • [P7880][Ynoi2006] rldcot
    [Ynoi2006]rldcot题目描述给定一棵\(n\)个节点的树,树根为\(1\),每个点有一个编号,每条边有一个边权。定义\(dep(x)\)表示一个点到根简单路径上边权的和,\(lca(x,y)\)......
  • 关于NOI2010“超级钢琴”的反思
    [NOI2010]超级钢琴题目描述小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。这架超级钢琴可以弹奏......
  • XMLSpy2006企业版汉化特别版
    XMLSpy2006企业版汉化特别版:​​http://soft.studa.com/Download.asp?ID=10255&sID=0​​我用迅雷速度可以达到约:180K/S 另外:MSXMLNotepad:​​http://www.soft666.com/s......