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.

按题意模拟。

 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

 

 ProblemF Parentheses

Upsolved.

题意:给出一个表达式,先判合法性,再判是否有括号冗余或者缺少。

思路:

直接判吧,数据里面有一个空行,不要多组读入。。。

vp的时候以为有(-b)这种东西,实际上没有。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 1000100
  5 char s[N];
  6 int id[N], len;
  7 
  8 bool ok()
  9 {
 10     len = strlen(s + 1);
 11     for (int i = 1; i <= len; ++i) 
 12     {
 13         if (isalpha(s[i]))
 14             id[i] = 0;
 15         else if (s[i] == '+' ||
 16                  s[i] == '-' ||
 17                  s[i] == '*' ||
 18                  s[i] == '/' ||
 19                  s[i] == '%')
 20                  id[i] = 1;
 21         else if (s[i] == '(')
 22             id[i] = 2;
 23         else
 24             id[i] = 3;         
 25     }
 26     if (id[1] == 3 || id[len] == 2) return false;
 27     if (id[1] == 1 || id[len] == 1) return false; 
 28     if (len == 1 && id[1] == 0)
 29         return true;
 30     for (int i = 2, x, y; i <= len; ++i)
 31     {
 32         x = id[i - 1], y = id[i];
 33         if (x == 0 && y == 0) 
 34             return false;
 35         if (x == 1 && y == 1)
 36             return false;
 37         if (x == 1 && y == 3)
 38             return false;
 39         if (x == 2 && y == 1)
 40             return false;
 41         if (x == 2 && y == 3)
 42             return false;
 43         if (x == 3 && y == 2)
 44             return false;
 45         if (x == 3 && y == 0)
 46             return false;
 47         if (x == 0 && y == 2)
 48             return false;
 49     }
 50     int cnt = 0; 
 51     for (int i = 1; i <= len; ++i)
 52     {
 53         if (id[i] == 2)
 54             ++cnt;
 55         else if (id[i] == 3)
 56         {
 57             if (cnt == 0) 
 58                 return false;
 59             --cnt;
 60         }
 61     }
 62     return cnt == 0;
 63 }
 64 
 65     // 0 alpha
 66     // 1 + - * / %
 67     // 2 (
 68     // 3 )
 69 
 70 bool work()
 71 {
 72     if (len == 1) return true;
 73     int cnt = 0, sym = 0;
 74     for (int i = 1; i <= len; ++i)
 75         sym += (id[i] == 1);
 76     stack <int> sta;
 77     for (int i = 1; i <= len; ++i)
 78     {
 79         if (id[i] == 0)
 80             continue;
 81         else if (id[i] <= 2)
 82             sta.push(id[i]);
 83         else if (id[i] == 3)
 84         {
 85             int flag = 0;
 86             while (!sta.empty())
 87             {
 88                 int top = sta.top(); sta.pop();
 89                 if (top == 2)
 90                     break;
 91                 if (top == 1) 
 92                     ++flag; 
 93             }        
 94             if (flag == 1) ++cnt;
 95             else
 96                 return false;
 97         }
 98     }
 99     return cnt == sym - 1; 
100 }
101 
102 int main()
103 {
104     gets(s + 1);
105     {
106         len = strlen(s + 1);
107         //if (len == 0) continue;
108         int now = 0;
109         for (int i = 1; i <= len; ++i)
110             if (s[i] != ' ')
111                 s[++now] = s[i];
112         s[++now] = 0;
113 //        cout << s + 1 << endl;
114         if (!ok()) puts("error");
115         else
116             puts(work() ? "proper" : "improper"); 
117     }
118     return 0;
119 }
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

 

posted @ 2019-03-02 18:16  Dup4  阅读(2545)  评论(0编辑  收藏  举报