UOJ132 NOI2015 小園丁與老司機

2022-05-08 04:51:10 字數 2961 閱讀 7093

作者部落格:

正解:dp+上下界網路流

解題報告:

第一、二問是一起的,dp一遍可以解決。

具體而言,f[i]記錄到達i的最優值,g[i]記錄前驅結點。

按y分層,不同層之間直接轉,左上右上的一條直線上的點x、y座標的和或者差相等,map儲存最後的值(寫轉入會方便一些)。

同一層之間有一點麻煩,考慮一定是從乙個點走進這一層之後,把一邊的所有點遍歷完之後再走向另一邊,從某個點走出這一層。

這個用字首和字尾最大值維護一下就可以了,輸出方案的時候就記錄一下這個點是從同一層還是從之前的層轉移過來的,就可以確定經過的點了。

第三問的話,我們可以通過前兩問,得到每個點的f,對於可能出現在最優解上的邊,我們都拎出來,然後建圖。

考慮題目要求我們什麼。因為每條邊都至少要被經過一次,就可以理解成求下界為1上界為inf的最小流。

就變成了有上下界的最小流問題了,這道題的建圖方式是:超級源點s向所有in[i]-out[i]>0的點連容量為in[i]-out[i]的邊,所有in[i]-out[i]<0的點向超級匯點t連容量為out[i]-in[i]的邊,原邊容量為inf。

跑一遍最大流,最後用滿流-最大流即為所求。

ps:我開始是用vector存下所有的可行轉移,然後調了乙個晚上調不出,小點都過了,大點有的ac有的wa...

今天早上一來機房,痛下決心,task3重寫!

換成了重新dp一遍,倒著做一遍,再正著連邊,這樣做就好調很多了...

建議:不要在腦子不清醒的時候寫這道題,這會讓你懷疑自己長了乙個假腦子...  

如果發現自己除錯不出來了,建議換一種寫法或者重寫一遍。祝你身體健康

//it is made by ljh2000

#include #include #include #include #include #include #include #include using namespace std;

typedef long long ll;

const int maxn = 50011;

const int maxm = 300011;

const int mod = 300007;

const int inf = (1<<29);

int n,f[maxn],g[maxn],from[maxn],from2[maxn],ans,dui[maxn],belong[maxn],le[maxn],ri[maxn],ycnt;

int ecnt,first[maxn],in[maxn],hcnt,s,t,deep[maxn],tot,dp[maxn];

bool same[maxn],vis[maxn];

mapmp[maxn];

struct nodea[maxn];

struct edgee[maxm];

struct bianb[maxm];

inline bool cmpy(node q,node qq)

struct hash

inline int query(int x)

inline void insert(int x,int val)

next[++ecnt]=first[cc]; first[cc]=ecnt; to[ecnt]=x; w[ecnt]=val;

}}t1,t2,t3;

inline void dp()

} for(int j=l;j<=r;j++)

} for(int j=l;j<=r;j++)

} //同層之間的轉移,一定是從pos走入,然後走到邊界,再往回走,從某個點走出

pos=l;//儲存最大的位置,字首max

for(int j=l+1;j<=r;j++)

} pos=r;//字尾max

for(int j=r-1;j>=l;j--)

} for(int j=l;j<=r;j++)

if(f[j]f[pos]) pos=i;

while(pos)

else

pos=from2[pos];

pos=from[pos];

} else

} for(int i=top;i>=1;i--) printf("%d ",a[dui[i]].id); puts("");

}inline void dp2()

} for(int j=l;j<=r;j++)

} for(int j=l;j<=r;j++)

} pos=l;

for(int j=l+1;j<=r;j++)

pos=r;

for(int j=r-1;j>=l;j--)

for(int j=l;j<=r;j++) dp[j]=max(dp[j],g[j]); }}

inline void build()

for(int j=l;j<=r;j++)

for(int j=l;j<=r;j++)

} ecnt=1; s=n+1; t=s+1;

for(int i=1;i<=hcnt;i++)

for(int i=1;i<=n;i++)

}inline bool bfs()

} if(deep[t]==-1) return false;

return true;

}inline int dinic(int x,int remain)

} return flow;

}inline void work()

sort(a+1,a+n+1,cmpy); a[0].x=a[0].y=a[n+1].x=a[n+1].y=-inf;

dp();

print();

dp2();

build();

while(bfs())

tot-=dinic(s,inf);

printf("%d",tot);

}int main()

UOJ130 NOI2015 荷馬史詩

作者部落格 追逐影子的人,自己就是影子。荷馬 allison 最近迷上了文學。她喜歡在乙個慵懶的午後,細細地品上一杯卡布奇諾,靜靜地閱讀她愛不釋手的 荷馬史詩 但是由 奧德賽 和 伊利亞特 組成的鴻篇巨制 荷馬史詩 實在是太長了,allison 想通過一種編碼方式使得它變得短一些。一部 荷馬史詩 中...

UOJ 131 NOI2015 品酒大會

題鏈 題解 網上大多數的方法都是用並查集維護。這裡呢,給出另一種自己yy的解法 但實際上本質差不多吧 字尾陣列,rmq,單調棧 1 預處理 1 首先對字串字尾排序,得到 sa i rank i height i 2 然後維護出 l i 表示在字尾陣列中,排名最小 記其排名為 l i 的字尾與排名為 ...

UOJ 131 NOI 2015 品酒大會

求出字尾陣列和height陣列後,從大到小掃相似度進行合併,每次相當於合併兩個緊挨著的區間。合併區間可以用並查集來實現,每個區間的資訊都記錄在這個區間的並查集的根上,合併並查集時用乙個根的資訊更新另乙個根的資訊同時計算兩個答案。時間複雜度 o n log n include include incl...