洛谷 P4704 太極劍【貪心】
阿新 • • 發佈:2019-05-02
pre getchar() getchar b- names swa 正是 () spa
所以選定這個起點貪心分段即可
我的證明應該沒錯吧……?反正是A了
首先考慮分割線能分割一條線當且僅當分割線一個端點在這條線的ab中間,另一端點在外面,也就是分割線對應的一條弧不能同時有這條線的兩個端點
每條線的兩端點都染同色,然後分段,一段裏面顏色互不相同,分割線就是一段的開始連到結尾,割掉這段裏的顏色的線,求最小的段數ans,答案就是(ans+1)/2
暴力是要枚舉起點,考慮優化,一個起點不是最優一定是從最優分割的一個塊的中間開始分割的,也就是第一段向前延伸還能加進新點,現在考慮最短的線的a+1這個點作為起點,那麽這塊一定能延伸到最短的線的b,因為這是最短的,不可能有另一條線的兩個端點在同時(a+1,b)了,然後能到b,就不能向前延伸了,前面一個就是和b同色的a了
我的證明應該沒錯吧……?反正是A了
#include<iostream> #include<cstdio> using namespace std; const int N=1000005; int n,st,mn=1e9,c[N],v[N],ti,ans; int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } int main() { n=read(); for(int i=1;i<=n;i++) { int a=read(),b=read(); if(a>b) swap(a,b); c[a]=c[b]=c[a+n*2]=c[b+n*2]=i; if(b-a<mn) mn=b-a,st=a+1; } for(int i=st;i<=st+n*2-1;i++) if(c[i]) { if(v[c[i]]==ti) ans++,ti++;//,cerr<<i<<endl; v[c[i]]=ti; }//cerr<<ans<<endl; printf("%d\n",(ans+1)/2); return 0; }
洛谷 P4704 太極劍【貪心】