【[USACO08JAN]haybale猜測Haybale Guessing】
阿新 • • 發佈:2019-01-01
抄題解.jpg
完全完全不會啊,這道題簡直太神了
不過抄題解可真開心
首先這道題目保證了每一個位置上的數都是不同的,那麼就能得到第一種判斷不合法的方式
如果兩個區間的最小值一樣,但是兩個區間的交集為空集,那麼就是不合法的
因為最小值肯定來自於同一個位置
之後就是第二種情況
上面那兩個紅色區間的最小值是\(4\),但是下面那個被完全包含的綠色區間的最小值是\(3\)這顯然非常不合法
但是如果是這個樣子呢
顯然是可以的,因為那些\(3\)可以來自紅色區間以外的位置
就有不行了,因為這個時候\(3\)又只能來自於那個較小的綠色區間了,而那個較小的綠色區間又被紅色完全覆蓋了
這個時候就能得出第二個判斷方法
如果最小值相同的區間,其交集被最小值比它的區間的並集覆蓋,那麼就不合法
所以我們需要覆蓋並集,判斷交集是否被完全覆蓋
顯然區間的交集和並集隨手就能求出來,但是覆蓋這個問題得需要一棵線段樹來判斷
同時為了方便的進行判斷\(2\),我們得讓區間的最小值是有序的,所以一個一個掃是行不通了,我們得二分答案,找到最後一個合法的位置\(+1\)就是答案了
程式碼
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define LL long long #define re register #define maxn 25005 #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) struct Seg { int x,y,q; }a[maxn],b[maxn]; int l[4000005],r[4000005],d[4000005],tag[4000005]; int n,m; inline int read() { char c=getchar(); int x=0; while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); return x; } void build(int x,int y,int i) { l[i]=x,r[i]=y; if(x==y) return; int mid=x+y>>1; build(x,mid,i<<1),build(mid+1,y,i<<1|1); } void clear(int x,int y,int i) { d[i]=0,tag[i]=0; if(x==y) return; int mid=x+y>>1; clear(x,mid,i<<1),clear(mid+1,y,i<<1|1); } inline void pushdown(int i) { if(!tag[i]) return; tag[i<<1]=tag[i<<1|1]=1; d[i<<1]=r[i<<1]-l[i<<1]+1; d[i<<1|1]=r[i<<1|1]-l[i<<1|1]+1; tag[i]=0; } void change(int x,int y,int i) { if(x<=l[i]&&y>=r[i]) { d[i]=r[i]-l[i]+1; tag[i]=1; return; } pushdown(i); int mid=l[i]+r[i]>>1; if(y<=mid) change(x,y,i<<1); else if(x>mid) change(x,y,i<<1|1); else change(x,y,i<<1|1),change(x,y,i<<1); d[i]=d[i<<1]+d[i<<1|1]; } int query(int x,int y,int i) { if(x<=l[i]&&y>=r[i]) return d[i]; pushdown(i); int mid=l[i]+r[i]>>1; if(y<=mid) return query(x,y,i<<1); if(x>mid) return query(x,y,i<<1|1); return query(x,y,i<<1)+query(x,y,i<<1|1); } inline int cmp(Seg A,Seg B) { return A.q>B.q; } inline int check(int now) { for(re int i=1;i<=now;i++) b[i]=a[i]; std::sort(b+1,b+now+1,cmp); clear(1,n,1); int pre=1,nl=b[1].x,nr=b[1].y,Ul=b[1].x,Ur=b[1].y; for(re int i=2;i<=now;i++) { if(b[i].q==b[pre].q) { nl=max(nl,b[i].x); Ul=min(Ul,b[i].x); Ur=max(Ur,b[i].y); nr=min(nr,b[i].y); } else { if(nl>nr) return 0; if(query(nl,nr,1)==nr-nl+1) return 0; change(Ul,Ur,1); pre=i; nl=Ul=b[i].x,nr=Ur=b[i].y; } } if(nl>nr) return 0; if(query(nl,nr,1)==nr-nl+1) return 0; return 1; } int main() { n=read(),m=read(); for(re int i=1;i<=m;i++) a[i].x=read(),a[i].y=read(),a[i].q=read(); build(1,n,1); int L=1,R=m; int ans=0; while(L<=R) { int mid=L+R>>1; if(check(mid)) L=mid+1,ans=mid; else R=mid-1; } if(ans==m) puts("0"); else printf("%d\n",ans+1); return 0; }