codeforces 1027F. Session in BSU

Polycarp studies in Berland State University. Soon he will have to take his exam. He has to pass exactly nn exams.

For the each exam ii there are known two days: aiai — day of the first opportunity to pass the exam, bibi — day of the second opportunity to pass the exam (ai<biai<bi). Polycarp can pass at most one exam during each day. For each exam Polycarp chooses by himself which day he will pass this exam. He has to pass all the nn exams.

Polycarp wants to pass all the exams as soon as possible. Print the minimum index of day by which Polycarp can pass all the nn exams, or print -1 if he cannot pass all the exams at all.

Input

The first line of the input contains one integer nn (1n1061≤n≤106) — the number of exams.

The next nn lines contain two integers each: aiai and bibi (1ai<bi1091≤ai<bi≤109), where aiai is the number of day of the first passing the ii-th exam and bibi is the number of day of the second passing the ii-th exam.

Output

If Polycarp cannot pass all the nn exams, print -1. Otherwise print the minimum index of day by which Polycarp can do that.

大意:

一个人可以在 ai 和 bi 两个时间完成时间i,给定 n 个事件,询问是否可以完成。

解题思路:

图论构造好题。

方案要匹配,总是要替换的。

一个方案被占用,很大程度上是需要方案的替换的

注意到这一点,假设一个方案 i 的替换方案为 j ,当方案 k 进入考虑时,若与 i 冲突,看看是替换好,还是自己退步好。

选择劣质的状态作为新的替换方案。

假设一个时间 i 为一个点,那么可以动态构建这样的树形结构:在 i 时间被占用后,而想要将 i 方案退化。那么这时将 i 的父亲指向其替换方案。

我们可以发现,此时的退化方案就是 i 退化或者另一端退化,这样树就堆叠合并到了一起。

换句话说,当一个时间指向自己的劣化方案,那么这样顺着找下去就是最终的让步方案了。

我可能说的不好,那就来几张图:

红色点代表可以被选的时间,白点代表已经被选的时间,那么初始状态就是上图。

现在a1=1,b1=3更新,那么就是:

若a2=1,b2=4更新,显然此时最优方案就是总时间为3,更新时1被占用,寻找劣化方案。

我们可以证明,这样合并树会导致最终每棵树只有点可用

所以就是并查集喽。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 class Auto_disperse{
  5     private:
  6         struct int_2{
  7             int val;
  8             int rnk;
  9             int no;
 10             bool friend operator < (int_2 x,int_2 y){return x.val<y.val;}
 11         };
 12         struct Ruye{
 13             int_2 line[10000000];
 14             int top;
 15             void sort(void){std::sort(line,line+top);return ;}
 16             void push_back(int_2 x){line[top++]=x;return ;}
 17             int size(void){return top;}
 18             void clear(void){top=0;return ;}
 19         }tmp;
 20         int cnt;
 21     public:
 22         void disp(int *a,int &len,int *ans)
 23         {
 24             tmp.clear();
 25             cnt=0;
 26             for(int i=1;i<=len;i++)
 27                 tmp.push_back((int_2){a[i],0,i});
 28             tmp.sort();
 29             cnt=1;
 30             tmp.line[0].rnk=1;
 31             for(int i=1;i<tmp.size();i++)
 32             {
 33                 if(tmp.line[i].val!=tmp.line[i-1].val)
 34                     cnt++;
 35                 tmp.line[i].rnk=cnt;
 36             }
 37             cnt=1;
 38             a[1]=tmp.line[0].val;
 39             ans[1]=tmp.line[0].rnk;
 40             for(int i=1;i<tmp.size();i++)
 41             {
 42                 if(tmp.line[i].val==tmp.line[i-1].val)
 43                     continue;
 44                 cnt++;
 45                 a[cnt]=tmp.line[i].val;
 46                 ans[cnt]=tmp.line[i].rnk;
 47             }
 48             len=cnt;
 49             return ;
 50         }
 51         int query(int *a,int *ans,int len,int san)
 52         {
 53             int l=1,r=len;
 54             while(l<=r)
 55             {
 56                 int mid=(l+r)>>1;
 57                 if(a[mid]==san)
 58                     return ans[mid];
 59                 if(a[mid]<san)
 60                     l=mid+1;
 61                 else
 62                     r=mid-1;
 63             }
 64             return ans[l];
 65         }
 66 }Dac;
 67 int fa[4000001];
 68 int n;
 69 int tot;
 70 int tmp[5000000];
 71 int val[5000000];
 72 int a[4000000];
 73 int b[4000000];
 74 int finf(int x)
 75 {
 76     if(!x)
 77         return 0;
 78     return x==fa[x]?x:fa[x]=finf(fa[x]);
 79 }
 80 void debug(int cmd)
 81 {
 82     if(cmd==1)
 83     {
 84         puts("Dac works:");
 85         for(int i=1;i<=tot;i++)
 86             printf("%d ",tmp[i]);
 87         puts("");
 88         for(int i=1;i<=tot;i++)
 89             printf("%d ",val[i]);
 90         puts("");
 91         return ;
 92     }
 93     if(cmd==2)
 94     {
 95         puts("a and b val:");
 96         for(int i=1;i<=n;i++)
 97             printf("%d ",a[i]);
 98         puts("");
 99         for(int i=1;i<=n;i++)
100             printf("%d ",b[i]);
101         puts("");
102         return ;
103     }
104 }
105 int exam(void)
106 {
107     int ans=-1;
108     for(int i=1;i<=n;i++)
109     {
110         int fx=finf(a[i]);
111         int fy=finf(b[i]);
112         if(fx>=fy)
113             std::swap(fx,fy);
114         if(fx==0)
115         {
116             if(fy==0)
117                 return -1;
118             fa[fy]=0;
119             ans=std::max(ans,fy);
120         }
121         fa[fx]=fy;
122         if(fx==fy)
123             fa[fx]=0;
124         ans=std::max(fx,ans);
125     }
126     return Dac.query(val,tmp,tot,ans);
127 }
128 int main()
129 {
130 //    printf("%d
",(sizeof(Dac)+sizeof(fa)+sizeof(tmp)+sizeof(val)+sizeof(a)+sizeof(b))/1024/1024);
131     scanf("%d",&n);
132     for(int i=1;i<=n;i++)
133     {
134         scanf("%d%d",&a[i],&b[i]);
135         tmp[++tot]=a[i];
136         tmp[++tot]=b[i];
137     }
138 //    debug(1);
139     Dac.disp(tmp,tot,val);
140     for(int i=1;i<=tot;i++)
141         fa[i]=i;
142 //    debug(1);
143 //    debug(2);
144     for(int i=1;i<=n;i++)
145     {
146         a[i]=Dac.query(tmp,val,tot,a[i]);
147         b[i]=Dac.query(tmp,val,tot,b[i]);
148     }
149 //    debug(2);
150     printf("%d
",exam());
151     return 0;
152 }
原文地址:https://www.cnblogs.com/blog-Dr-J/p/9857179.html