2018-2019 ACM-ICPC, Asia Seoul Regional Contest

ProblemA Circuits

Solved.

题意:

有$n$个矩形,可以放两条平行与$x$轴的线,求怎么放置两条无线长的平行于$x$轴的线,使得他们与矩形相交个数最多

如果一个矩形同时与两条线相交,只算一次。

思路:

离散化后枚举一根线,另一根线用线段树维护,扫描线思想

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 400010
  5 int n;
  6 int b[N]; 
  7 int x[N], y[N];
  8 vector <int> in[N], out[N];
  9 int ans[N];
 10 
 11 namespace SEG
 12 {
 13     struct node
 14     {
 15         int Max, lazy;
 16         node () {}
 17         node (int Max, int lazy) : Max(Max), lazy(lazy) {}
 18         void init() { Max = lazy = 0; }
 19         void add(int x)
 20         {
 21             Max += x;
 22             lazy += x;
 23         }
 24         node operator + (const node &other) const
 25         {
 26             node res; res.init();
 27             res.Max = max(Max, other.Max);
 28             return res;
 29         }
 30     }a[N << 2];
 31     void build(int id, int l, int r)
 32     {
 33         a[id].init();
 34         if (l == r)
 35             return;
 36         int mid = (l + r) >> 1;
 37         build(id << 1, l, mid);
 38         build(id << 1 | 1, mid + 1, r);
 39     }
 40     void pushdown(int id)
 41     {
 42         if (!a[id].lazy) return;
 43         a[id << 1].add(a[id].lazy);
 44         a[id << 1 | 1].add(a[id].lazy);
 45         a[id].lazy = 0;
 46     }
 47     void update(int id, int l, int r, int ql, int qr, int x)
 48     {
 49         if (l >= ql && r <= qr)
 50         {
 51             a[id].add(x);
 52             return;
 53         }
 54         int mid = (l + r) >> 1;
 55         pushdown(id);
 56         if (ql <= mid) update(id << 1, l, mid, ql, qr, x);
 57         if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, x);
 58         a[id] = a[id << 1] + a[id << 1 | 1];
 59     } 
 60     int query(int id, int l, int r, int pos)
 61     {
 62         if (l == r) return a[id].Max;
 63         int mid = (l + r) >> 1;
 64         pushdown(id);
 65         if (pos <= mid) return query(id << 1, l, mid, pos);
 66         else return query(id << 1 | 1, mid + 1, r, pos);
 67     }
 68 }
 69 
 70 void Hash()
 71 {
 72     sort(b + 1, b + 1 + b[0]);
 73     b[0] = unique(b + 1, b + 1 + b[0]) - b - 1;
 74     for (int i = 1; i <= n; ++i) x[i] = lower_bound(b + 1, b + 1 + b[0], x[i]) - b;
 75     for (int i = 1; i <= n; ++i) y[i] = lower_bound(b + 1, b + 1 + b[0], y[i]) - b;
 76 }
 77 
 78 int main()
 79 {
 80     while (scanf("%d", &n) != EOF)
 81     {
 82         b[0] = 0;  
 83         for (int i = 1; i < N; ++i)
 84             in[i].clear(), out[i].clear();
 85         for (int i = 1, tmp; i <= n; ++i)
 86         {
 87             scanf("%d%d%d%d", &tmp, y + i, &tmp, x + i);
 88 //            cout << x[i] << " " << y[i] << endl;
 89             b[++b[0]] = x[i];
 90             b[++b[0]] = y[i];
 91         }
 92         Hash();
 93         SEG::build(1, 1, b[0]);
 94         for (int i = 1; i <= n; ++i)
 95         {
 96             in[x[i]].push_back(i);
 97             out[y[i]].push_back(i);
 98             SEG::update(1, 1, b[0], x[i], y[i], 1);            
 99         }
100         int res = 0;
101         for (int i = 1; i <= b[0]; ++i)
102             ans[i] = SEG::query(1, 1, b[0], i);
103         for (int i = 1; i <= b[0]; ++i)
104         {
105             for (auto it : in[i])
106                 SEG::update(1, 1, b[0], x[it], y[it], -1);
107             res = max(res, ans[i] + SEG::a[1].Max);
108             for (auto it : out[i])
109                 SEG::update(1, 1, b[0], x[it], y[it], 1);
110         }
111         printf("%d\n", res);
112     }
113     return 0;
114 }
View Code

Problem D Go Latin

Solved.

扫描二维码关注公众号,回复: 5386366 查看本文章

按题意模拟。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t;
 5 map <string, string> mp;
 6 
 7 int main()
 8 {
 9     mp["a"] = "as";
10     mp["i"] = "ios";
11     mp["y"] = "ios";
12     mp["l"] = "les";
13     mp["n"] = "anes";
14     mp["ne"] = "anes";
15     mp["o"] = "os";
16     mp["r"] = "res";
17     mp["t"] = "tas";
18     mp["u"] = "us";
19     mp["v"] = "ves";
20     mp["w"] = "was";
21     ios::sync_with_stdio(false);
22     cin.tie(0); cout.tie(0);
23     cin >> t;
24     string s;
25     while (t--)
26     {
27         cin >> s;
28         int len = s.size();
29         string tmp = "";
30         tmp += s[len - 1];
31         if (mp.find(tmp) != mp.end())
32         {
33             s.erase(s.begin() + len - 1);
34             s += mp[tmp];
35         }
36         else
37         {
38             tmp = "";
39             tmp += s[len - 2];
40             tmp += s[len - 1];
41             if (mp.find(tmp) != mp.end())
42             {
43                 s.erase(s.begin() + len - 2, s.end());
44                 s += mp[tmp];
45             }
46             else
47                 s += "us";
48         }
49         cout << s << "\n";
50     }
51     return 0;
52 }
View Code

ProblemE LED

Upsolved.

题意:求一个分段函数的最小最大值

思路:

注意$v = 0$的时候,其余部分二分,贪心验证

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 300010
 6 struct node
 7 {
 8     ll v, l;
 9     void scan()
10     {
11         scanf("%lld%lld", &v, &l);
12         l *= 10ll;
13     }
14     bool operator < (const node &other) const { return v < other.v; }
15 }a[N];
16 int n;
17 
18 bool check(ll x)
19 {
20     int i;
21     ll l1, l2;
22     for (i = 1; i <= n; ++i)
23     {
24         if (a[i].l > x)
25             break;
26     }
27     if (i > n) return true;
28     ll Max = 0, Min = (ll)1e11;
29     for (; i <= n; ++i)
30     {
31         Max = max(Max, a[i].l);
32         Min = min(Min, a[i].l);
33         if (Max - (Max + Min) / 2 > x)
34             break;
35         l1 = (Max + Min) / 2;
36     }
37     if (i > n) return true;
38     Max = 0, Min = (ll)1e11;
39     for (; i <= n; ++i)
40     {
41         Max = max(Max, a[i].l);
42         Min = min(Min, a[i].l);
43         if (Max - (Max + Min) / 2 > x)
44             break;
45         l2 = (Max + Min) / 2;
46     }  
47     //cout << x << " " << l1 << " " << l2 << endl;
48     if (i <= n) return false;
49     return l2 >= l1;    
50 }
51 
52 int main()
53 {
54     while (scanf("%d", &n) != EOF)
55     {
56         for (int i = 1; i <= n; ++i) a[i].scan();
57         sort(a + 1, a + 1 + n);
58         ll base = 0;
59         int j = 0;
60         for (int i = 1; i <= n; ++i)
61         {
62             if (a[i].v == 0)
63                 base = max(base, a[i].l);
64             else
65                 a[++j] = a[i];
66         }
67         n = j; 
68         ll l = 0, r = (ll)1e11, res = -1;
69         while (r - l >= 0)
70         {
71             ll mid = (l + r) >> 1;
72             if (check(mid))
73             {
74                 res = mid;
75                 r = mid - 1;
76             }
77             else
78                 l = mid + 1;
79         }
80         res = max(res, base);
81         ll x = res % 10;
82         res /= 10;
83         printf("%lld.%lld\n", res, x);
84     }
85     return 0;
86 }
View Code

ProblemK TV Show Game

Solved.

题意:$k$个灯, $n$个人, 每个人猜三个位置的灯的颜色, 要求构造出使得所有人都猜对两个或两个以上数量的灯的颜色的序列。

思路:枚举每个灯的状态, 2-SAT求解。

(2-SAT 不熟练啊 果然还是需要练一练)

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e4 + 10;
 6 
 7 struct node{
 8     int lamp1, lamp2, lamp3;
 9     int color1, color2, color3;
10 }arr[maxn];
11 
12 int k, n;
13 int vis[maxn << 1];
14 vector<int>People[maxn], lamp[maxn];//R 0 B 1
15 int Stack[maxn], top;
16 
17 void Init()
18 {
19     for(int i = 1; i < maxn; ++i) People[i].clear();
20     for(int i = 1; i < maxn; ++i) lamp[i].clear();
21 }
22 
23 bool DFS(int u)
24 {
25     if(vis[u ^ 1]) return false;
26     if(vis[u]) return true;
27     vis[u] = 1;
28     Stack[top++] = u;
29     for(auto it : lamp[u])
30     {
31         for(auto v : People[it]) if(v != u)
32         {
33             if(!DFS(v ^ 1)) return false;
34         }
35     }
36     return true;
37 }
38 
39 bool Twosat(int n)
40 {
41     memset(vis, 0, sizeof vis);
42     for(int i = 2; i <= n; i += 2)
43     {
44         if(vis[i] || vis[i ^ 1]) continue;
45         top = 0;
46         if(!DFS(i)) 
47         {
48             while(top) vis[Stack[--top]] = 0;
49             if(!DFS(i ^ 1)) return false;
50         }
51     }
52     return true;
53 }
54 
55 int main()
56 {
57     while(~scanf("%d %d", &k, &n))
58     {
59         Init();
60         for(int i = 1; i <= n; ++i)
61         {
62             char a, b, c;
63             scanf("%d %c %d %c %d %c", &arr[i].lamp1, &a, &arr[i].lamp2, &b, &arr[i].lamp3, &c);
64             
65             arr[i].color1 = (a == 'B');
66             arr[i].color2 = (b == 'B');
67             arr[i].color3 = (c == 'B');
68             
69             People[i].push_back(arr[i].lamp1 * 2 + (arr[i].color1 ^ 1));
70             lamp[arr[i].lamp1 * 2 + (arr[i].color1 ^ 1)].push_back(i);
71     
72             People[i].push_back(arr[i].lamp2 * 2 + (arr[i].color2 ^ 1));
73             lamp[arr[i].lamp2 * 2 + (arr[i].color2 ^ 1)].push_back(i);
74     
75             People[i].push_back(arr[i].lamp3 * 2 + (arr[i].color3 ^ 1));
76             lamp[arr[i].lamp3 * 2 + (arr[i].color3 ^ 1)].push_back(i);
77         }
78         if(Twosat(2 * k))
79         {
80             for(int i = 1; i <= k; ++i)
81             {
82                 if(vis[2 * i]) putchar('R');
83                 else putchar('B');
84             }
85             putchar('\n');
86         }
87         else puts("-1");
88     }
89     return 0;
90 }
View Code

ProblemL Working Plan

Solved.

题意:$m$个人, $n$天, 每个人一旦开始工作需要连续工作$w$天, 工作完w天后需要休息$h$天, 每天需要$d_i$个人, 每个人要求工作$W_i$天, 求方案。

思路:贪心, 优先使得剩余工作天数多的人工作。

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 typedef long long ll;
  6 
  7 const int maxn = 2e3 + 10;
  8 
  9 struct node{
 10     int id;
 11     int st, ed;
 12     int workday;
 13     node(){}
 14     node(int id, int st, int ed, int workday): id(id), st(st), ed(ed), workday(workday){}
 15     bool operator < (const node  &other) const{
 16         if(st != other.st) return st > other.st;
 17         else return workday < other.workday;
 18     }
 19 };
 20 
 21 bool cmp(node a, node b)
 22 {
 23     return a.workday < b.workday;
 24 }
 25 
 26 int n, m,w, h;
 27 int W[maxn], d[maxn];
 28 priority_queue<node>q;
 29 priority_queue<int, vector<int>, greater<int> >Day;
 30 vector<int>ans[maxn];
 31 node Stack[maxn];
 32 int top;
 33 
 34 void Init()
 35 {
 36     while(!q.empty()) q.pop();
 37     while(!Day.empty()) Day.pop();
 38     for(int i = 1; i <= m; ++i) ans[i].clear();
 39 }
 40 
 41 int main()
 42 {
 43     while(~scanf("%d %d %d %d", &m, &n, &w, &h))
 44     {
 45         Init();
 46         for(int i = 1; i <= m; ++i) scanf("%d", W + i);
 47         for(int i = 1; i <= n; ++i) scanf("%d", d + i);
 48         for(int i = 1; i <= m; ++i) q.push(node(i, 0, 0, W[i]));
 49         bool flag = true;
 50         int cnt = 0;
 51         top = 0;
 52         for(int i = 1; i <= n; ++i)
 53         {
 54             while(!Day.empty())
 55             {
 56                 if(Day.top() < i) Day.pop();
 57                 else break;
 58             }
 59             int daysize = Day.size();
 60             if(daysize > d[i])
 61             {
 62                 flag = false;
 63                 break;
 64             }
 65             if(daysize == d[i]) continue;
 66             while(!q.empty())
 67             {
 68                 if(q.top().st <= i) 
 69                 {
 70                     Stack[++top] = q.top();
 71                     q.pop();
 72                 }
 73                 else
 74                 {
 75                     break;
 76                 }
 77             }
 78             sort(Stack + 1, Stack + 1 + top, cmp);
 79             while(Day.size() < d[i])
 80             {
 81                 if(top < 1)
 82                 {
 83                     flag = false;
 84                     break;
 85                 }
 86                 node tmp = Stack[top--];
 87                 tmp.st = i;
 88                 ans[tmp.id].push_back(i);
 89                 tmp.st += w;
 90                 Day.push(tmp.st - 1);
 91                 tmp.st += h;
 92                 tmp.workday -= min(w, n - i + 1);
 93                 if(tmp.workday) q.push(tmp);
 94                 else cnt++;
 95             }
 96             if(Day.size() != d[i]) flag= false;
 97             if(flag == false) break;
 98         }
 99         if(cnt != m) flag = false;
100         if(flag)
101         {
102             puts("1");
103             for(int i = 1; i <= m; ++i) for(int j = 0, len = ans[i].size(); j < len; ++j) printf("%d%c", ans[i][j], " \n"[j == len - 1]);
104         }
105         else puts("-1");
106     }
107     return 0;
108 }
View Code

猜你喜欢

转载自www.cnblogs.com/Dup4/p/10462263.html