zoukankan      html  css  js  c++  java
  • 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 >>>>>>
    ", (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
    ";
    73         else if(dp[i][1] == inf)
    74             cout << "unknown
    ";
    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 >>>>>>
    ", (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
    ", 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 >>>>>>
    ", (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 ? '
    ' : ' ');
    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 >>>>>>
    ", (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 >>>>>>
    ", (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
    ", r1[n+1-i], r2[i]);
    47     } else if(sum1 < sum2) {
    48         for(int i = 1; i <= n; i++)
    49             printf("%d %d
    ", r1[i], r2[n+1-i]);
    50     } else {
    51         for(int i = 1; i <= n; i++)
    52             printf("%d %d
    ", i, i);
    53     }
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    重点词笔记
    pycharm tips
    标注精简过的问题如何导入问题库
    增加权重
    word2vec训练出来的相似词歧义
    算法测试及对比度进一步增强
    Python 命名笔记
    债务重组的会计处理方法
    实质性方案与综合性方案的区别
    什么叫认定层次
  • 原文地址:https://www.cnblogs.com/rootial/p/4100856.html
Copyright © 2011-2022 走看看