JZOJ 5627. 【NOI2018模拟4.3】paint
Description
Input
Output
Sample Input
樣例輸入1
10 10 4
1 6
4 1
6 9
9 4
樣例輸入2
10 10 4
2 2
4 4
7 7
9 9
Sample Output
樣例輸出1
32
樣例輸出2
26
Data Constraint
Solution
- 先貼上原題題解:
為方便統計答案,先加入兩個邊界點 (0,0) 和 (w,h) 。
之后將所有點按 X 坐標從小到大排序。
我們對于直線 l:y=h2 ,上下同時維護各一個值遠離逐漸 l 的單調棧。
棧中存著許多線段,線段樹中存著兩個棧元素縱坐標的相反數 ?Y1?Y2 ,
則取出后加上 h 就是對應矩形的寬了。
其中 zjp_shadow的博客 講的很詳細:
(虛線 為中線,黑色 是當前單調棧里的,紅色 是現在將過來的一個線段)
我們將兩個棧頂線段的答案進行更改,將這些線段的橫著的答案變小它坐標的相應的差值。
這個就可以直接在線段樹上做加減法就行了。
然后我們用這條 綠色 和 紅色 的線段一起,共同構成一個新的線段存進單調棧中去。
為了同時得到矩形的長,我們把值在減去當前的橫坐標 Xi ,
之后在查詢時加上目前的橫坐標 Xi+1 ,這樣就得出了對應矩形的長 Xi+1?Xi 。
這樣也就得到了當前矩形一半周長的最優答案。
注意每做完一個點 i 時,要及時更新答案,并將 i 點的信息單點加到線段樹上。
為了避免 i+1 不能成功進入棧中,需要在棧末尾加入一個極值點 (i,h/0) 來保證入棧。
而對于直線 x=w2 也同理,交換坐標再做一遍即可。
時間復雜度 O(N?log?N) 。
Code
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; const int N=2e5+5; struct data {int x,y; }a[N],f[N<<2],st1[N]/*down*/,st2[N]/*up*/; int w,h,n,ans; int top1,top2,qx,qy,qz; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline bool cmp(data x,data y) {return x.x<y.x; } inline int max(int x,int y) {return x>y?x:y; } void change(int v,int l,int r) {if(qx<=l && r<=qy){f[v].x+=qz;f[v].y+=qz;return;}int mid=l+r>>1;if(qx<=mid) change(v<<1,l,mid);if(qy>mid) change(v<<1|1,mid+1,r);f[v].x=max(f[v<<1].x,f[v<<1|1].x)+f[v].y; } inline void solve() {memset(f,top1=top2=0,sizeof(f));sort(a+1,a+1+n,cmp);for(int i=1;i<n;i++){if(a[i].y<=h>>1){int t=i-1;while(top1 && st1[top1].y<a[i].y){qx=st1[top1].x,qy=t,qz=st1[top1].y-a[i].y;change(1,1,n);t=st1[top1--].x-1;}if(t^i-1) st1[++top1]=(data){t+1,a[i].y};}else{int t=i-1;while(top2 && st2[top2].y>a[i].y){qx=st2[top2].x,qy=t,qz=a[i].y-st2[top2].y;change(1,1,n);t=st2[top2--].x-1;}if(t^i-1) st2[++top2]=(data){t+1,a[i].y};}st1[++top1]=(data){i,0};st2[++top2]=(data){i,h};qx=qy=i,qz=h-a[i].x;change(1,1,n);ans=max(ans,f[1].x+a[i+1].x);} } int main() {w=read(),h=read(),n=read();for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();a[++n]=(data){0,0};a[++n]=(data){w,h};solve();for(int i=1;i<=n;i++) swap(a[i].x,a[i].y);swap(w,h);solve();printf("%d",ans<<1);return 0; }總結
以上是生活随笔為你收集整理的JZOJ 5627. 【NOI2018模拟4.3】paint的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 5625. 【NOI2018模
- 下一篇: JZOJ 5628. 【NOI2018模