NEERC 2014, Eastern subregional contest

最近做的一场比赛,把自己负责过的题目记一下好了。

Problem B URAL 2013 Neither shaken nor stirred

题意:一个有向图,每个结点一个非负值,可以转移到其他结点。初始时刻从结点出发,然后每次到达一个结点询问上一个到达的正值结点的权值,离开结点时也要询问一下,因为当前结点可能为正数,答案就是这个值了,如果不存在这个样的正权值输出“sober",或者不明确时输出“unkonwn”。

分析:可以当做树形dp来做。dp[u][0]表示进入结点时上一个正权值,dp[u][1]表示离开结点时的正权值, val[u]表示结点u权值,inf表示不明确情况。

转移这样来做:

对于边u->v,首先考虑dp[v][1], val[v] != 0时, dp[v][1] = val[v],否则dp[v][1] = dp[v][0]。

如果v没有访问过,dp[v][0] = dp[u][1], v访问过,那么dp[v][0] != dp[u][1]时,更新dp[v][0] = inf,并且 当val[v] = 0时,要从v点重新出发dfs, 因为此时dp[v][1]值也会变化。

 

代码:

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define esp 1e-8
 5 #define lowbit(x) ((x)&(-x))
 6 #define lson   l, m, rt<<1
 7 #define rson   m+1, r, rt<<1|1
 8 #define sz(x) ((int)((x).size()))
 9 #define pb push_back
10 #define in freopen("solve_in.txt", "r", stdin);
11 #define out freopen("solve_out.txt", "w", stdout);
12 
13 #define bug(x) printf("Line : %u >>>>>>\n", (x));
14 #define inf 0x0f0f0f0f
15 using namespace std;
16 typedef long long LL;
17 typedef pair<int, int> PII;
18 typedef map<int, int> MPS;
19 const int maxn = 100000 + 100;
20 vector<int> g[maxn];
21 int vis[maxn];
22 int dp[maxn][2], val[maxn];
23 void dfs(int u, int fa) {
24     if(vis[u]) {
25         if(dp[fa][1] != dp[u][0]) {
26             dp[u][0] = inf;
27             if(!val[u]) {
28                 dp[u][1] = inf;
29                 for(int i = 0; i < sz(g[u]); i++) {
30                     int v = g[u][i];
31                     dfs(v, u);
32                 }
33             }
34         }
35         return;
36     }
37     vis[u] = 1;
38     dp[u][0] = dp[fa][1];
39     dp[u][1] = val[u] ? val[u] : dp[u][0];
40     for(int i = 0; i < sz(g[u]); i++) {
41         int v = g[u][i];
42         dfs(v, u);
43     }
44 }
45 int main() {
46     
47     int n;
48     scanf("%d", &n);
49     for(int i = 1; i <= n; i++) {
50         int m;
51         scanf("%d%d", &val[i], &m);
52         for(int j = 0; j < m; j++) {
53             int u;
54             scanf("%d", &u);
55             g[i].pb(u);
56         }
57     }
58     vis[1] = 1;
59     dp[1][0] = 0;
60     dp[1][1] = val[1] ? val[1] : 0;
61     for(int i = 0; i < sz(g[1]); i++) {
62         int u = g[1][i];
63         dfs(u, 1);
64     }
65     for(int i = 1; i <= n; i++) {
66         if(dp[i][0] == 0)
67             cout << "sober ";
68         else if(dp[i][0] == inf)
69             cout << "unknown ";
70         else cout << dp[i][0] << ' ';
71         if(dp[i][1] == 0)
72             cout << "sober\n";
73         else if(dp[i][1] == inf)
74             cout << "unknown\n";
75         else cout << dp[i][1] << endl;
76     }
77     return 0;
78 }
View Code

 

Problem C URAL 2014 Zhenya moves from parents

意:共有n张收支凭据,根据当前的收到的凭据算出账户欠款,当前不足支出时,从账户扣除,收到一笔钱时把钱拿在手上不会去还信用卡上的钱,所以

信用卡欠款会越来越多的。

将时间离散化,排个序,然后以此建立线段树,每次将凭据对应的金额插入更新。线段树两个节点值,dep[rt],表示当前区间时账户欠款,tot[rt]表示当前区间时能够剩下的现金。具体更新:

 

dep[rt] = dep[rt<<1] + min(0LL, tot[rt<<1]+dep[rt<<1|1]);
tot[rt] = tot[rt<<1|1] + max(tot[rt<<1]+dep[rt<<1|1], 0LL);

代码:

 

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define esp 1e-8
 5 #define lowbit(x) ((x)&(-x))
 6 #define lson   l, m, rt<<1
 7 #define rson   m+1, r, rt<<1|1
 8 #define sz(x) ((int)((x).size()))
 9 #define pb push_back
10 #define in freopen("solve_in.txt", "r", stdin);
11 #define out freopen("solve_out.txt", "w", stdout);
12 
13 #define bug(x) printf("Line : %u >>>>>>\n", (x));
14 #define inf 0x0f0f0f0f
15 using namespace std;
16 typedef long long LL;
17 typedef pair<int, int> PII;
18 typedef map<string, int> MPS;
19 const int maxn = 100000 + 100;
20 
21 struct Node {
22     int mon, day, h, mi, c, id;
23     Node() {}
24     Node(int mon, int day, int h, int mi, int c, int id):mon(mon), day(day), h(h), mi(mi), c(c), id(id) {}
25     bool operator < (const Node &o)const {
26         if(mon == o.mon) {
27             if(day == o.day) {
28                 if(h == o.h) return mi < o.mi;
29                 return h < o.h;
30             }
31             return day < o.day;
32         }
33         return mon < o.mon;
34     }
35 } b[maxn];
36 int a[maxn];
37 char s[100];
38 int pos[maxn];
39 LL dep[maxn<<2], tot[maxn<<2];
40 void PushUp(int rt) {
41     dep[rt] = dep[rt<<1] + min(0LL, tot[rt<<1]+dep[rt<<1|1]);
42     tot[rt] = tot[rt<<1|1] + max(tot[rt<<1]+dep[rt<<1|1], 0LL);
43 }
44 void update(int l, int r, int rt, int p, int c) {
45     if(p == l && p == r) {
46         if(c > 0)
47             tot[rt] = c;
48         else dep[rt] = c;
49         return;
50     }
51     int m = (l+r)>>1;
52     if(p <= m)
53         update(lson, p, c);
54     else update(rson, p, c);
55     PushUp(rt);
56 }
57 
58 int main() {
59     
60     int n;
61     scanf("%d", &n);
62     for(int i = 1; i <= n; i++) {
63         int c, day, mon, h, mi;
64         scanf("%d %d.%d %d:%d", &c, &day, &mon, &h, &mi);
65         b[i] = Node(mon, day, h, mi, c, i);
66         a[i] = c;
67     }
68     sort(b+1, b+n+1);
69     for(int i = 1; i <= n; i++)
70         pos[b[i].id] = i;
71     for(int i = 1; i <= n; i++) {
72         update(1, n, 1, pos[i], a[i]);
73         LL ans = dep[1];
74         printf("%I64d\n", ans);
75     }
76     return 0;
77 }
View Code

 

 

 

Problem F URAL 2017 Best of a bad lot

意:有n个人处在不同的位置,声称目击哪些人也在场,这些人中有一些是嫌疑人,但是他们为了洗脱嫌疑会让他们的证词不相互矛盾,而其他人则会说出真正的情况。问最小的嫌疑团体。

分析:2个人所在地方不同,但是都目击同一个人,那么这两个人必定有一个为嫌疑人,很显然可以建立一个二分图,每次给图中结点着色,选取最少的加入到答案中。

代码:

 

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define esp 1e-8
 5 #define lowbit(x) ((x)&(-x))
 6 #define lson   l, m, rt<<1
 7 #define rson   m+1, r, rt<<1|1
 8 #define sz(x) ((int)((x).size()))
 9 #define pb push_back
10 #define in freopen("solve_in.txt", "r", stdin);
11 #define out freopen("solve_out.txt", "w", stdout);
12 
13 #define bug(x) printf("Line : %u >>>>>>\n", (x));
14 #define inf 0x0f0f0f0f
15 using namespace std;
16 typedef long long LL;
17 typedef pair<int, int> PII;
18 typedef map<string, int> MPS;
19 
20 const int maxn = 444;
21 typedef set<int> :: iterator IT;
22 
23 vector<int>g[maxn];
24 set<int> a[maxn];
25 vector<string> name;
26 
27 int vis[maxn];
28 vector<int> tmp[2];
29 void dfs(int u, int col) {
30     tmp[col].pb(u);
31     vis[u] = 1;
32     for(int i = 0; i < sz(g[u]); i++) {
33         int v = g[u][i];
34         if(vis[v]) continue;
35         dfs(v, col^1);
36     }
37 }
38 int main() {
39     
40     int n;
41     scanf("%d", &n);
42     for(int i = 1; i <= n; i++) {
43         string str;
44         cin >> str;
45         name.pb(str);
46         int m;
47         scanf("%d", &m);
48         for(int j = 0; j < m; j++) {
49             int k;
50             scanf("%d", &k);
51             a[i].insert(k);
52         }
53         a[i].insert(i);
54     }
55     for(int i = 1; i <= n; i++) {
56         for(int j = i+1; j <= n; j++) {
57             if(name[i-1] != name[j-1]) {
58                 for(IT it = a[i].begin(); it != a[i].end(); it++)
59                     if(a[j].count(*it)) {
60                         g[i].pb(j);
61                         g[j].pb(i);
62                         break;
63                     }
64             }
65         }
66     }
67     vector<int> ans;
68     for(int i = 1; i <= n; i++) {
69         if(vis[i] || sz(g[i]) == 0) continue;
70         tmp[0].clear();
71         tmp[1].clear();
72         dfs(i, 0);
73         if(tmp[0].size() > tmp[1].size()) tmp[0] = tmp[1];
74         for(int j = 0; j < sz(tmp[0]); j++)
75             ans.pb(tmp[0][j]);
76     }
77     if(sz(ans)) {
78         cout << sz(ans) << endl;
79         for(int i = 0; i < ans.size(); i++)
80             printf("%d%c", ans[i], i == sz(ans)-1 ? '\n' : ' ');
81     } else {
82         puts("1");
83         puts("1");
84     }
85     return 0;
86 }
View Code

 

 

 

Problem G URAL 2018 The Debut Album

题意:每个元素可以为1,或2,组成n个元素的排列,且连续1的个数不能超过a,连续2的个数不能超过b问有多少种方式.

分析:dp[now][0][len],表示当前位为1,前面已经有len个连续1了,

转移:dp[now][0][len] = dp[pre][0][len-1],len > 1

   dp[now][0][len] = sum{dp[pre][1][k]| 1 <= k <= b},len == 1

当前位为0时同理。

代码:

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define esp 1e-8
 5 #define lowbit(x) ((x)&(-x))
 6 #define lson   l, m, rt<<1
 7 #define rson   m+1, r, rt<<1|1
 8 #define sz(x) ((int)((x).size()))
 9 #define pb push_back
10 #define in freopen("solve_in.txt", "r", stdin);
11 #define out freopen("solve_out.txt", "w", stdout);
12 
13 #define bug(x) printf("Line : %u >>>>>>\n", (x));
14 #define inf 0x0f0f0f0f
15 using namespace std;
16 typedef long long LL;
17 typedef pair<int, int> PII;
18 typedef map<int, int> MPS;
19 const int maxn = 50000 + 100;
20 const int M = (int)1e9 + 7;
21 LL dp[2][2][310];
22 int main() {
23 
24     int n, a, b;
25     scanf("%d%d%d", &n, &a, &b);
26     dp[1][1][1] = dp[1][0][1] = 1;
27     for(int i = 2; i <= n; i++) {
28         int now = i&1;
29         int pre = 1^now;
30 
31         for(int j = 1; j <= a; j++) {
32             dp[now][0][j] = 0;
33             if(j == 1) {
34                 for(int k = 1; k <= b; k++)
35                     dp[now][0][j] = (dp[now][0][j] + dp[pre][1][k])%M;
36             } else
37                 dp[now][0][j] = (dp[now][0][j] + dp[pre][0][j-1])%M;
38         }
39         for(int j = 1; j <= b; j++) {
40             dp[now][1][j] = 0;
41             if(j == 1) {
42                 for(int k = 1; k <= a; k++)
43                     dp[now][1][j] = (dp[now][1][j] + dp[pre][0][k])%M;
44             } else
45                 dp[now][1][j] = (dp[now][1][j] + dp[pre][1][j-1])%M;
46         }
47     }
48     LL ans = 0;
49     int now = n&1;
50     for(int i = 1; i <= a; i++)
51         ans = (ans + dp[now][0][i])%M;
52     for(int i = 1; i <= b; i++)
53         ans = (ans + dp[now][1][i])%M;
54     cout << ans << endl;
55     return 0;
56 }
View Code

 


Problem H URAL 2019 Pair: normal and paranormal

题意:括号匹配

分析:多重括号匹配,每种字母代表一个,A只能和a匹配。

代码:



Problem J URAL 2021 Scarily interesting!

题意:安排两个队伍n场比赛的得分,使得悬念保持的越长越好。

分析:赢的那方从小到大,另一方从大到小。

代码:

 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define esp 1e-8
 5 #define lowbit(x) ((x)&(-x))
 6 #define lson   l, m, rt<<1
 7 #define rson   m+1, r, rt<<1|1
 8 #define sz(x) ((int)((x).size()))
 9 #define pb push_back
10 #define in freopen("solve_in.txt", "r", stdin);
11 #define out freopen("solve_out.txt", "w", stdout);
12 
13 #define bug(x) printf("Line : %u >>>>>>\n", (x));
14 #define inf 0x0f0f0f0f
15 using namespace std;
16 typedef long long LL;
17 typedef pair<int, int> PII;
18 typedef map<int, int> MPS;
19 const int maxn = 1111;
20 int a[maxn], b[maxn], r1[maxn], r2[maxn];
21 bool cmp1(int x, int y) {
22     return a[x] > a[y];
23 }
24 bool cmp2(int x, int y) {
25     return b[x] > b[y];
26 }
27 int main() {
28     
29     int n;
30     scanf("%d", &n);
31     int sum1 = 0, sum2 = 0;
32     for(int i = 1; i <= n; i++) {
33         scanf("%d", &a[i]);
34         sum1 += a[i];
35         r1[i] = i;
36     }
37     for(int i = 1; i <= n; i++) {
38         scanf("%d", b+i);
39         sum2 += b[i];
40         r2[i] = i;
41     }
42     sort(r1+1, r1+n+1, cmp1);
43     sort(r2+1, r2+n+1, cmp2);
44     if(sum1 > sum2) {
45         for(int i = 1; i <= n; i++)
46             printf("%d %d\n", r1[n+1-i], r2[i]);
47     } else if(sum1 < sum2) {
48         for(int i = 1; i <= n; i++)
49             printf("%d %d\n", r1[i], r2[n+1-i]);
50     } else {
51         for(int i = 1; i <= n; i++)
52             printf("%d %d\n", i, i);
53     }
54     return 0;
55 }
View Code

 

你可能感兴趣的:(test)