JZOJ 3731. 【NOIP2014模拟7.10】庐州月
Description
【引子】
橋上的戀人入對出雙
橋邊紅藥嘆夜太漫長
月也搖晃人也彷徨
烏蓬里傳來了一曲離殤
廬州月光灑在心上
月下的你不復(fù)當(dāng)年模樣
太多的傷難訴衷腸
嘆一句當(dāng)時只道是尋常
廬州月光梨花雨涼
如今的你又在誰的身旁
家鄉(xiāng)月光深深烙在我心上
卻流不出當(dāng)年淚光——Vae《廬州月》
【問題描述】
小 G 是出生在廬州的一位同學(xué),當(dāng)他高中畢業(yè)后,回到了自己的家鄉(xiāng)。然而家鄉(xiāng)已不復(fù)當(dāng)年模樣,在高中表現(xiàn)優(yōu)秀的小G 決定承擔(dān)起家鄉(xiāng)的一件重任,那就是修理已經(jīng)破爛不堪的石橋。
家鄉(xiāng)中共有n 個石橋等待修理,對于第i 個石橋,我們定義兩個參數(shù)pi,vi,其中pi表示修理石橋的最小花費值,vi表示石橋需要的最小美化需求度。今天,小G 已了解到修理廠共有m 種不同的修理原料,對于第i 種原料,可以對任意
一個石橋的美化度增加di,當(dāng)然這也需要花費hi的費用。由于發(fā)貨場的修理原料有限,對于任意一種修理原料,只有一件,也就是說小G 只能選擇購買和不購買,對于第i 種修理材料能成功修理第j 個石橋的條件是:當(dāng)且僅當(dāng)hi ≥ pj,di ≥vj。現(xiàn)在,已知這n 個石橋修理的最小花費值,最小美化需求度,以及m種修理原料的費用,可對石橋增加的美化度值,請你幫助小G完成這個修理任務(wù)。
Input
第一行包括兩個正整數(shù),n,m。
接下來 n 行中,每行包括兩個正整數(shù)pi,vi。
接下來 m行中,每行包括兩個正整數(shù)hi,di。
Output
只有一個整數(shù),為最小修理花費。如果無法完成修理任務(wù),則輸出一個整數(shù)
-1。
Sample Input
2 3
2 3
5 9
3 10
3 5
6 11
Sample Output
9
【樣例說明】
其中一種可行的方案是:使用第1 種材料,修理第1 個石橋,使用第3 種材
料,修理第2 個石橋,最小修理花費為3 + 6 = 9。
Data Constraint
Solution
這是一道典型的貪心題!
把石橋和修理方法都按美化需求度從大到小排序,一個一個石橋修理。
那么維護(hù)兩個指針,對于一個石橋,就能知道“可能”可以修理的那些方案。
之后,排除掉之前已經(jīng)選過的那些,其中必有一個最佳方案。
顯然, 最佳的一定是花費大于等于當(dāng)前石橋且其花費最小的!
可是維護(hù)這樣的集合有一些困難,復(fù)雜度一般為 O(NlogN)
這樣再加上掃描本身的 O(N),是會時間超限的。
于是我們的平衡樹算法——Splay,就隆重登場了!
只需基本的插入、刪除和求后繼操作就可以在 O(logN) 內(nèi)實現(xiàn)了。
Code
#include<cstdio> #include<algorithm> using namespace std; const int N=100001; struct data {int x,y; }a[N],b[N]; int root,tot; int s[N][2],fa[N],key[N]; long long ans; inline int read() {int data=0; char ch=0;while(ch<'0' || ch>'9') ch=getchar();while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();return data; } inline bool cmp(data a,data b) {return a.y>b.y; } inline bool pd(int x) {return x==s[fa[x]][1]; } inline void rotate(int x) {int y=fa[x],w=pd(x);if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;fa[s[y][w]=s[x][w^1]]=y;s[fa[y]=x][w^1]=y; } inline void splay(int x) {for(int y;y=fa[x];rotate(x))if(fa[y]) rotate(pd(x)==pd(y)?y:x);root=x; } inline int search(int x,int v) {while(key[x]!=v)if(v<key[x]){if(!s[x][0]) break;x=s[x][0];}else{if(!s[x][1]) break;x=s[x][1];}return x; } inline void ins(int &x,int y,int v) {if(!x){x=++tot;key[x]=v;fa[x]=y;return;}ins(s[x][key[x]<=v],x,v); } inline void del(int v) {int k=search(root,v);splay(k);if(!s[k][0]){fa[root=s[k][1]]=0;key[k]=s[k][1]=0;return;}fa[s[k][0]]=0;splay(search(s[k][0],1e9));if(s[root][1]=s[k][1]) fa[s[root][1]]=root;key[k]=s[k][0]=s[k][1]=0; } inline int find(int v) {if(!root) return 0;int x=root;while(true){if(key[x]<v){if(!s[x][1]) return 0;x=s[x][1];continue;}if(s[x][0]){int y=s[x][0];while(key[y]<v && s[y][1]) y=s[y][1];if(key[y]>=v){x=y;continue;}}return x;} } int main() {int n=read(),m=read();for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();for(int i=1;i<=m;i++) b[i].x=read(),b[i].y=read();sort(a+1,a+1+n,cmp);sort(b+1,b+1+m,cmp);for(int i=1,j=1;i<=n;i++){while(j<=m && b[j].y>=a[i].y){ins(root,0,b[j++].x);splay(tot);}int k=find(a[i].x);if(!k){printf("-1");return 0;}ans+=key[k];del(key[k]);}printf("%lld",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的JZOJ 3731. 【NOIP2014模拟7.10】庐州月的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ 1588: [HNOI2002
- 下一篇: JZOJ 1533. 郁闷的gxg