poj 2010 Moo University - Financial Aid (貪心+線段樹)
轉載請註明出處,謝謝http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
騙一下訪問量。。。。
題意大概是:從c箇中選出n個,使得總花費小於等於f,保證價值的中位數最大
http://poj.org/problem?id=2010
做法:按價值排序之後,列舉中位數,然後對於小於中位數的部分貪心選出花費最小的n/2個,大於的部分也貪心選出花費最小的n/2個,然後比較總花費與f的關係。
可以用兩個線段樹維護一下,左部分便是每次insert一個,比較當前的第k小的大小,如果更小則remove掉原來的第k小,insert一個新的。
右部分便是每次remove一個,然後更新第k小。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#define lson step<<1
#define rson step<<1|1
#define LL long long
using namespace std;
const int N = 100005;
struct Node{
int cost,val;
bool operator<(const Node n)const{
return val<n.val;
}
}a[N];
struct Seg_tree{
int left,right;
int small,large;
}L[N<<2];
int m,n,f,x[N],tot;
LL Left=0,Right=0;
void bulid(int step,int l,int r){
L[step].left=l;
L[step].right=r;
L[step].small=L[step].large=0;
if(l==r) return ;
int m=(l+r)>>1;
bulid(lson,l,m);
bulid(rson,m+1,r);
}
void insert(int step,int pos,int kind){
if(!kind) L[step].small++;
else L[step].large++;
if(L[step].left==pos&&pos==L[step].right) return ;
int m=(L[step].left+L[step].right)>>1;
if(pos<=m) insert(lson,pos,kind);
else insert(rson,pos,kind);
}
int query(int step,int k,int kind){
if(L[step].left==L[step].right) return L[step].left;
int m=(L[step].left+L[step].right)>>1;
if(!kind){
if(L[lson].small>=k) return query(lson,k,kind);
else return query(rson,k-L[lson].small,kind);
}
else{
if(L[lson].large>=k) return query(lson,k,kind);
else return query(rson,k-L[lson].large,kind);
}
}
void remove(int step,int pos,int kind){
if(!kind) L[step].small--;
else L[step].large--;
if(L[step].left==L[step].right) return ;
int m=(L[step].left+L[step].right)>>1;
if(pos<=m) remove(lson,pos,kind);
else remove(rson,pos,kind);
}
int main(){
scanf("%d%d%d",&m,&n,&f);
for(int i=0;i<n;i++){
scanf("%d%d",&a[i].val,&a[i].cost);
x[i]=a[i].cost;
}
sort(a,a+n);
sort(x,x+n);
tot=unique(x,x+n)-x;
bulid(1,1,tot);
for(int i=0;i<m/2;i++){
Left+=(LL)a[i].cost;
int pos=lower_bound(x,x+tot,a[i].cost)-x+1;
insert(1,pos,0);
}
for(int i=m/2+1;i<n;i++){
int pos=lower_bound(x,x+tot,a[i].cost)-x+1;
if(i<m){
Right+=(LL)a[i].cost;
insert(1,pos,1);
}
else{
int idx=query(1,m/2,1);
if(a[i].cost<x[idx-1]) Right=Right-x[idx-1]+a[i].cost;
insert(1,pos,1);
}
}
int ans=-1;
for(int i=m/2;i<n-m/2;i++){
if((LL)Left+Right+a[i].cost<=f){
ans=max(ans,a[i].val);
}
int pos=lower_bound(x,x+tot,a[i].cost)-x+1;
int idx=query(1,m/2,0);
if(a[i].cost<x[idx-1]){
Left-=(LL)x[idx-1];
Left+=(LL)a[i].cost;
remove(1,idx,0);
insert(1,pos,0);
}
pos=lower_bound(x,x+tot,a[i+1].cost)-x+1;
remove(1,pos,1);
idx=query(1,m/2,1);
if(a[i+1].cost<x[idx-1]){
Right-=(LL)a[i+1].cost;
Right+=(LL)x[idx-1];
}
}
printf("%d\n",ans);
return 0;
}
相關文章
- POJ 3667 Hotel 線段樹
- poj 2667 hotel 線段樹
- [貪心]最大線段重疊
- [Hackerrank University Codesprint 5] Sword profit (李超線段樹)
- BZOJ5249: [2018多省省隊聯測]IIIDX(線段樹 貪心)
- 【貪心】POJ 3617:Best Cow Line
- Luogu P4425 轉盤 題解 [ 黑 ] [ 線段樹 ] [ 貪心 ] [ 遞迴 ]遞迴
- 洛谷P3586 [POI2015]LOG(貪心 權值線段樹)
- Codeforces 1070C - Cloud Computing 思路+線段樹+貪心 (2018-2019 ICPC, NEERC)Cloud
- POJ2253 Frogger【並查集+貪心】並查集
- POJ 2777 Count Color (線段樹+狀態壓縮)
- bzoj1858: [Scoi2010]序列操作(線段樹)
- TZOJ 8472 : Tree (重鏈剖分+線段樹) POJ 3237
- POJ 3468 A Simple Problem with Integers (線段樹 區間共加)
- POJ1797 Heavy Transportation【並查集+貪心】並查集
- POJ 2528 Mayor's posters (線段樹 區間更新+離散化)
- Sunscreen POJ - 3614(防曬油) 貪心-優先佇列佇列
- bzoj2426: [HAOI2010]工廠選址(貪心)
- 一種型別的樹貪心型別
- bzoj2151: 種樹(貪心+堆)
- POJ 3468 【區間修改+區間查詢 樹狀陣列 | 線段樹 | 分塊】陣列
- POJ 2376 Cleaning Shifts(區間貪心之區間覆蓋)
- BZOJ 1835 [ZJOI2010]base 基站選址:線段樹優化dp優化
- 線段樹
- 線~段~樹
- 01 線段樹
- 線段樹--RMQMQ
- 【模版】線段樹
- 線段樹模板
- 線段樹 hate it
- 貪心
- 貪心演算法-找不重疊的區間段演算法
- ut.cpp 最大線段並減線段交 [線段樹]
- 李超線段樹
- 線段樹進階
- 權值線段樹
- 線段樹筆記筆記
- Segment Tree(線段樹)
- 線段樹入門