• Gym


    题面

    题意:有3e5个人排成一列,然后Li,Ri表示每个人可以站在[Li,Ri]中的一个,然后M(1e6)个限制条件,某个人一定要在某个人前面,求一种合法方案,无解输出-1

    题解:首先可以想到对于限制条件,先进行拓扑排序,如果不能则无解

            针对拓扑排序的结果,可以更精确每个人站的位置的区间[Li,Ri]

            然后从后往前进行考虑,我们考虑每个位置由谁来坐比较好,那我们策略是,R能覆盖这个位置的中,L最大的那一个来最优,

            我们一直维护一个R的堆,每次我们将R超过当前位置的人都丢进一个新的堆里,这个堆按L大来排序,再使用最大的那个L

            如此贪心做完,不行则无解

      1 #include<bits/stdc++.h>
      2 #define lld long long 
      3 #define N 300005
      4 using namespace std;
      5 vector<int> g[N];
      6 int n,m,du[N],x,y,ans[N];
      7 struct rec
      8 {
      9     int l,r,id;
     10     bool operator <(const rec& a)const 
     11     {
     12         if (r!=a.r) return r<a.r;
     13         return l>a.l;
     14     }
     15 }a[N];
     16 struct ssy
     17 {
     18     int l,r,id;
     19     bool operator <(const ssy& a)const 
     20     {
     21         return l<a.l;
     22     }
     23 }b[N];
     24 int ask()
     25 {    
     26     priority_queue<ssy>q;
     27     priority_queue<rec>qq;
     28     ssy st;
     29     while (!q.empty()) q.pop();    
     30     while (!qq.empty()) qq.pop();
     31     for (int i=1;i<=n;i++) if (du[i]==0) qq.push(a[i]);
     32     for (int i=n;i>=1;i--)
     33     {
     34         while (!qq.empty())
     35         {
     36             if (qq.top().r<i) break;
     37             q.push(b[qq.top().id]);
     38 //            cout << b[qq.top().id].id << endl;
     39             qq.pop();
     40         }
     41         if (q.empty() || q.top().l>i) return 0;
     42         st=q.top();
     43 //        cout<<st.id << endl;
     44         q.pop();
     45         
     46         //cout<<"id"<<st.id<<endl;
     47         ans[i]=st.id;
     48         
     49         for (int j=0;j<g[st.id].size();j++)
     50         {
     51             int u=g[st.id][j];
     52             du[u]--;
     53             if (du[u]==0) qq.push(a[u]);
     54         }
     55     }
     56     return 1;
     57 }
     58 int c[N];
     59 bool dfs(int u)
     60 {
     61     c[u]=-1;
     62     for (int v=0;v<g[u].size();v++)
     63     {
     64         int to=g[u][v];
     65         if (c[to]<0) 
     66         {
     67             //cout<<"u xxx:"<<u<<endl;
     68             //cout<<"1 xxx:"<<to<<endl;
     69             return 0;
     70         }else
     71         if (!c[to] && !dfs(to)) 
     72         {
     73             //cout<<"u xxx:"<<u<<endl;
     74             //cout<<"1 xxx:"<<to<<endl;
     75             return 0;
     76         }
     77         a[u].l=max(a[u].l,a[to].l+1);
     78         b[u].l=a[u].l;
     79     }
     80     c[u]=1;
     81     return 1;
     82 }
     83 bool toposort()
     84 {
     85     memset(c,0,sizeof(c));
     86     for (int u=1;u<=n;u++) if (!c[u]) 
     87         if (!dfs(u)) return 0;
     88     return 1;    
     89 }
     90 int main()
     91 {
     92     scanf("%d%d",&n,&m);
     93     for (int i=1;i<=n;i++)
     94     {
     95         scanf("%d%d",&a[i].l,&a[i].r);a[i].id=i;
     96         b[i].l=a[i].l;
     97         b[i].r=a[i].r;
     98         b[i].id=a[i].id;
     99     }
    100     for (int i=1;i<=m;i++)
    101     {
    102         scanf("%d%d",&x,&y);
    103         g[y].push_back(x);
    104         du[x]++;
    105     }
    106     if (!toposort()) printf("-1
    ");else
    107     if (!ask()) printf("-1
    ");else
    108     for (int i=1;i<=n;i++) printf("%d
    ",ans[i]);
    109     
    110     
    111     //for (int i=1;i<=n;i++) cout<<a[i].l<<" "<<a[i].r<<endl;
    112 }
  • 相关阅读:
    【转】.net 在线播放各类视频
    引用母版页的内容页添加CSS文件
    NET上传大文件出现网页无法显示的问题 默认的上传文件大小是4M
    DropDownList1.Items.Insert 与 DropDownList1.Items.Add 的区别
    暑假集训8.10-网络流套树剖套线段树
    暑假集训8.10—网络流(黑白染色法)
    暑假集训8.7数据结构专题—网络流套线段树
    暑假集训8.7数据结构专题-线段树存直线
    暑假集训8.7数据结构专题-很妙的线段树( 觉醒力量(hidpower))
    可修改主席树&树上可修改主席树—树套树套树!!!
  • 原文地址:https://www.cnblogs.com/qywhy/p/10592284.html
Copyright © 2020-2023  润新知