洛谷P2564 [SCOI2009]生日礼物(单调队列)

传送门

准确的来说这个应该叫尺取法?

先对所有的点按$x$坐标进行排序

我们维护两个指针$l,r$,每一次令$r$不断右移直到所有颜色齐全,再不断右移$l$直到颜色数不足,那么此时$[l-1,r]$这个区间里的彩珠肯定能构成所有颜色,且不难发现不会有包含这一区间的方案比它更优

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define inf 0x3f3f3f3f
 7 using namespace std;
 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 9 char buf[1<<21],*p1=buf,*p2=buf;
10 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
11 inline int read(){
12     #define num ch-'0'
13     char ch;bool flag=0;int res;
14     while(!isdigit(ch=getc()))
15     (ch=='-')&&(flag=true);
16     for(res=num;isdigit(ch=getc());res=res*10+num);
17     (flag)&&(res=-res);
18     #undef num
19     return res;
20 }
21 const int N=1e6+5;
22 struct node{
23     int x,col;
24     inline bool operator <(const node &b)const
25     {return x<b.x;}
26 }a[N];
27 int cnt[105],tot,n,k,res=inf;
28 inline void add(int i){if(++cnt[a[i].col]==1) ++tot;}
29 inline void del(int i){if(--cnt[a[i].col]==0) --tot;}
30 int main(){
31 //    freopen("testdata.in","r",stdin);
32     n=read(),k=read();
33     for(int i=1;i<=k;++i){
34         int x=read();
35         for(int j=1;j<=x;++j) a[++tot].x=read(),a[tot].col=i;
36     }
37     tot=0,sort(a+1,a+1+n);
38     int l=1,r=0;
39     while(true){
40         while(tot<k&&r<n) add(++r);
41         if(r==n&&tot<k) break;
42         while(tot==k&&l<=r) del(l++);
43         cmin(res,a[r].x-a[l-1].x);
44     }
45     printf("%d\n",res);
46     return 0;
47 }

猜你喜欢

转载自www.cnblogs.com/bztMinamoto/p/9762232.html