SMU Winter 2024 Round #3 (Div.2)

1.New game(是一个拓扑排序板子稍微变形,但是循环加优先队列也可以做)

板子

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <utility>
 4 #include <queue>
 5 #include <cstring>
 6 #define x first
 7 #define y second
 8 
 9 using namespace std;
10 
11 const int N = 100010;
12 
13 int m,n;
14 int h[N] , e[N] , ne[N] , idx; //邻接表存图
15 int d[N]; //入度
16 queue <int> q,Q;
17 
18 //一个有像无环图至少有一个入度为0的点
19 
20 void add(int a,int b){
21     e[idx] = b , ne[idx] = h[a] , h[a] = idx++ ;
22 }
23 
24 bool topsort(){
25     for(int i=1;i<=m;i++) if(!d[i]) q.push(i); //将入度为0的点存入队列
26     while(q.size()){
27         int t = q.front();
28         Q.push(t);
29         q.pop();
30         for(int i = h[t]; i != -1; i = ne[i]){
31             d[e[i]]--;
32             if(d[e[i]]==0) q.push(e[i]);
33         }
34     }
35     return Q.size()==m;
36 }
37 
38 int main(){
39     memset(h , -1 , sizeof h);
40     int t;
41     cin>>t;
42     while(t--) {
43         cin >> m >> n;
44         for (int i = 1; i <= n; i++) {
45             int a, b;
46             cin >> a >> b;
47             add(a, b);
48             d[b]++;
49         }
50         if (topsort()) while (Q.size()) cout << Q.front() << ' ', Q.pop();
51         else cout << -1 << endl;
52     }
53     return 0;
54 }

循环做法

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <utility>
 4 #include <queue>
 5 #include <cstring>
 6 using namespace std;
 7 const int N=1e5+10;
 8 priority_queue<int,vector<int>,greater<int>> head;
 9 vector<int >g[N];
10 vector<int>ans;
11 int n,m;
12 int in[N];
13 void solve()
14 {
15     scanf("%d %d",&n,&m);
16     for(int i=1;i<=n;i++)
17     {
18         g[i].clear();
19         in[i]=0;
20     }
21     for(int i=1;i<=m;i++)
22     {
23         int a,b;
24         scanf("%d %d",&a,&b);
25         g[a].push_back(b);
26         in[b]++;
27     }
28     for(int i=1;i<=n;i++)if(in[i]==0)head.push(i);
29     while(head.size())
30     {
31         int t=head.top();
32         head.pop();
33         printf("%d ",t);
34         for(auto val:g[t])
35         {
36             in[val]--;
37             if(in[val]==0)head.push(val);
38         }
39     }
40     puts("");
41     return ;
42 }
43 int main()
44 {
45     int t;
46     scanf("%d",&t);
47     while(t--)solve();
48     return 0;
49 }

2.Kwords Find Kth Element(现将每个序列排序,再二分为mid,查询小于等于mid的数字数量sum,如果sum大于等于k就调低上限,否则调升)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 vector<long long>a[100005];
 4 long long aa,lll,m[100005] ,l,r,mid ,mid1,ll,rr,n,q,kk;
 5 long long k[100005],sum ,ans, ansans;
 6 int main()
 7 {
 8     ios::sync_with_stdio(false);
 9     cin.tie(0);cout.tie(0);
10     cin>>n;
11     for (int i=1;i<=n;i++) {
12         cin >> m[i];
13         a[i].push_back(0);
14         for (int j = 1; j <= m[i]; j++) {
15             cin >> aa;
16             a[i].push_back(aa);
17         }
18         sort(a[i].begin() + 1, a[i].end());
19     }
20     cin>>q;
21     for (int i=1;i<=q;i++)
22     {
23         cin>>lll;
24         for (int j=1;j<=lll;j++) {
25             cin >> k[j];
26         }
27         cin>>kk;
28         l=1;r=1e9;
29         while (l<=r)
30         {
31             mid=(l+r)/2;
32 
33             sum=0;
34 
35             for (int j=1;j<=lll;j++) {
36                 ll = 1;
37                 rr = m[k[j]];
38                 ans = 0;
39                 while (ll <= rr) {
40                     mid1 = (ll + rr) / 2;
41                     if (a[k[j]][mid1] <= mid) {
42                         ans = mid1;
43                         ll = mid1 + 1;
44                     } else rr = mid1 - 1;
45 
46                 }
47 
48                 sum = sum + ans;
49             }
50             if(sum>=kk)
51             {
52                 ansans=mid;
53                 r=mid-1;
54             }
55             else
56                 l=mid+1;
57         }
58         cout<<ansans<<"\n";
59     }
60 }

 

posted @ 2024-02-17 21:34  伊芙加登  阅读(30)  评论(0)    收藏  举报