库存
这些题目考试时费劲心思没有想出,考完后发现是一个有意思的贪心dp,挺奇妙的,没有接触过,所以记在这里,方便回顾。
数分考试
ZR提高十连测day9 T1 problem440
一共有$n$个人参加了考试。第$i$个人的名次区间是$[L_i,R_i]$。除此之外,又有$m$条其他信息,形如$u_i,v_i$,表示第$u_i$个人考的要比$v_i$好(即排名更低)。是否有一个合法的排名,满足上述所有的要求。如果有,请输出任意一组解,否则输出"-1"(不含括号)。$n \leq 3\times 10^5, m\le 10^6$
分析:
首先建反图拓扑,然后拓扑的过程中,判断是否存在环。用优先队列,每次弹出左端点最靠右的人,左端点相同弹右端点最靠右的,这样首先保证了图上的关系,然后又是尽量靠右的。记录一个Ti,从后往前依次更新第Ti名的人是谁。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #define fi(s) freopen(s,"r",stdin); 12 #define fo(s) freopen(s,"w",stdout); 13 using namespace std; 14 typedef long long LL; 15 16 char buf[100000], *p1 = buf, *p2 = buf; 17 #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) 18 inline int read() { 19 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 20 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 21 } 22 23 const int N = 300005; 24 25 struct Edge{ 26 int to, nxt; 27 Edge() { } 28 Edge(int a,int b) { to = a, nxt = b; } 29 }e[2000005]; 30 struct Node{ 31 int l, r, id; 32 bool operator < (const Node &A) const { 33 return l == A.l ? r < A.r : l < A.l; 34 } 35 }A[N]; 36 int head[N], deg[N], ans[N], n, En; 37 bool vis[N]; 38 priority_queue< Node >q; 39 40 void add_edge(int u,int v) { 41 ++En; e[En] = Edge(v, head[u]); head[u] = En; 42 } 43 bool topo() { 44 int L = 1, R = 0; 45 for (int i = 1; i <= n; ++i) 46 if (!deg[i]) q.push(A[i]); 47 int Ti = n; 48 while (!q.empty()) { 49 Node now = q.top(); q.pop(); 50 if (now.l > Ti || now.r < Ti) return 0; 51 vis[now.id] = 1; 52 ans[Ti --] = now.id; 53 for (int i = head[now.id]; i; i=e[i].nxt) 54 if ((--deg[e[i].to]) == 0) q.push(A[e[i].to]); 55 } 56 for (int i = 1; i <= n; ++i) 57 if (!vis[i]) return 0; 58 return 1; 59 } 60 int main() { 61 n = read(); int m = read(); 62 for (int i = 1; i <= n; ++i) 63 A[i].l = read(), A[i].r = read(), A[i].id = i; 64 for (int i = 1; i <= m; ++i) { 65 int u = read(), v = read(); 66 add_edge(v, u); deg[u] ++; 67 } 68 if (!topo()) { cout << -1; return 0; } 69 for (int i = 1; i <= n; ++i) printf("%d\n",ans[i]); 70 return 0; 71 } 72 /* 73 4 3 74 75 3 4 76 1 3 77 2 4 78 2 3 79 80 2 3 81 3 4 82 2 1 83 */