A:寻找爱吃饭的你。
水题,按照题意,用map映射一下,然后遍历找最大值即可。


#include <bits/stdc++.h>
using namespace std;
map <string, long long> mp;
int main(){
    //freopen("3.in", "r", stdin);
    //freopen("3.out", "w", stdout);
    int n;
    while(scanf("%d", &n) != EOF)
    {
        mp.clear();
        string a;
        long long x;
        for(int i = 1; i <= n; i++){
            for(int j = 0; j < 14; j++){
                cin >> a >> x;
                mp[a] += x;
            }
        }
        string ans;
        long long total = 0;
        for(map<string, long long> ::iterator it = mp.begin(); it != mp.end(); it++){
            if(it->second > total){
                total = it->second;
                ans = it->first;
            }
            else if(it->second == total && it->first < ans){
                ans = it->first;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

B,数学涛之神奇卡片 非常容易推出公式:m^n - (m-1)^n。然后快速幂A掉。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int mod=1e9+7;
LL qpow(LL x,LL y)
{
    LL ans=1;
    while(y){
        if(y%2) ans=ans*x%mod;
        x=x*x%mod;
        y/=2; } return ans; } int main() { //    freopen("4.in", "r", stdin);
//    freopen("4.out", "w", stdout);
    LL n,m;
    while(scanf("%lld%lld",&n,&m) != EOF){
        printf("%lld\n",(qpow(m,n)-qpow(m-1,n)+mod)%mod);
    }
    return 0;
}

C,数字拼接,贪心,直接按照a+b

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        vector<string> v;
        while(n--)
        {
            string s;
            cin >> s;
            v.push_back(s);
        }
        sort(v.begin(), v.end(), [](string & x, string & y)
        {
            return x + y < y + x;
        });
        for(auto i : v) printf("%s", i.c_str());
        printf("\n");
    }
}

D,版本号控制
排序。。。。

#include<bits/stdc++.h>
using namespace std;
char s[(int)1e7];
int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        set<vector<int> >st;
        while(n--)
        {
            scanf("%s",s);
            vector<int> v;
            istringstream ss(s);
            int x;
            while(ss >> x)
            {
                char c;
                ss >> c;
                v.push_back(x);
            }
            st.insert(v);
        }
        for(auto &i : st)
        {
            for(int j = 0; j < i.size(); j++)
            {
                printf("%d", i[j]);
                if(j == i.size() - 1) printf("\n");
                else printf(".");
            }
        }
    }
    return 0;
}

E,判断回文串。。。卡了内存,不能开数组,还卡了普通单Hash,要双Hash。。。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
const int MOD1 = 1e9 + 7;
const int MOD2 = 1e9 + 9;
void Update1(pair<uLL, uLL> &p, int x, pair<uLL, uLL> &val)
{
    p.first += x * val.first;
    p.first %= MOD1;
    p.second += x * val.second;
    p.second %= MOD2;
    val.first *= 131;
    val.first %= MOD1;
    val.second *= 131;
    val.second %= MOD2;
}
void Update2(pair<uLL, uLL> &p, int x)
{
    p.first *= 131;
    p.first += x;
    p.first %= MOD1;
    p.second *= 131;
    p.second += x;
    p.second %= MOD2;
}
int main()
{
    //freopen("2.in","r",stdin);
   //freopen("2.out","w",stdout);
    int n;
    while(~scanf("%d", &n))
    {
        char buf[100];
        gets(buf);
        int m = n / 2;
        if(n & 1)
        {
            pair<uLL, uLL> h1 = make_pair(0, 0), val = make_pair(1LL, 1LL), h2;
            for(int i = 1; i <= m; i++)
            {
                int c = getchar();
                Update1(h1, c, val);
            }
            n = getchar();
            Update1(h1, n, val);
            h2 = make_pair(n,n);
            for(int i = 1; i <= m; i++)
            {
                int c = getchar();
                Update2(h2, c);
            }
            if(h1 == h2) puts("YES");
            else puts("NO");
        }
        else
        {
            pair<uLL, uLL> h1 = make_pair(0, 0), val = make_pair(1LL, 1LL), h2 = make_pair(0, 0);
            for(int i = 1; i <= m; i++)
            {
                int c = getchar();
                Update1(h1, c, val);
            }
            for(int i = 1; i <= m; i++)
            {
                int c = getchar();
                Update2(h2, c);
            }
            if(h1 == h2) puts("YES");
            else puts("NO");
        }
    }
    return 0;
}

F, ZXY的神奇扑克牌,良心题,读懂题意后发现就是一个裸带权LCS。所以O(n*n)的DP就可以了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int add(char a, char b){
    if(a == 'R' && b == 'R') return 50;
    if(a == 'R'){
        if(b == 'A') return 20;
        if(b == 'K') return 15;
        if(b == 'Q') return 15;
        if(b == 'J') return 15;
        if(b == 'T') return 10;
        return b - '0';
    }
    if(b == 'R'){
        if(a == 'A') return 20;
        if(a == 'K') return 15;
        if(a == 'Q') return 15;
        if(a == 'J') return 15;
        if(a == 'T') return 10;
        return a - '0';
    }
    if(a == 'A') return 20;
    if(a == 'K') return 15;
    if(a == 'Q') return 15;
    if(a == 'J') return 15;
    if(a == 'T') return 10;
    return a - '0';
}
char a[maxn][3], b[maxn][3];
int n, dp[maxn][maxn];
int main(){
    while(scanf("%d", &n) != EOF)
    {
        if(n == 0) break;
        memset(dp, 0, sizeof(dp));
        for(int i = 1; i <= n; i++) scanf("%s", a[i]);
        for(int i = 1; i <= n; i++) scanf("%s", b[i]);
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                if(a[i][0] == b[j][0] || a[i][0] == 'R' || b[j][0] == 'R'){
                    dp[i][j] = max(dp[i][j], dp[i-1][j-1] + add(a[i][0], b[j][0]));
                }
            }
        }
        printf("%d\n", dp[n][n]*2);
    }
    return 0;
}

G, ZXY的不重叠区间问题 ,先按右端点排序,右端点相同的情况下按照左端点排序,然后对于没条线段的右端点,设dp[i]代表<=i点的最大权值和,我们去找<=这条线段的左端点的dp的最大值加上当前线段的权值更新当前的右端点的dp值,但是端点的数据太大,所以我们先要把端点离散化,之后就可以了吗?我们发现直接暴力是O(n*m)的,显然过不了。注意到我们去找<=这条线段的左端点的dp的最大值 这句话,我们可以随便用一种数据结构来维护这个东西,这题就做完了。当然不离散化,直接用unorder_map和动态开点线段树也是可以过的。

代码1:普通离散化


//

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5;
long long mp[maxn];
vector <int> v;
int getid(int x){
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}
struct node{
    int l, r, v;
    node(){}
    node(int l, int r, int v) : l(l), r(r), v(v) {}
    bool operator <(const node &rhs) const{
        if(r == rhs.r) return l < rhs.l;
        return r < rhs.r;
    }
}a[maxn];
namespace bit{
    int mx;
    inline int lowbit(int x){return x&-x;}
    inline void update(int pos, long long x){for(int i = pos; i <= mx; i+=lowbit(i)) mp[i] = max(mp[i], x);}
    inline long long query(int x){long long res = 0; for(int i = x; i; i-=lowbit(i)) res = max(res, mp[i]); return res;}
} using namespace bit;
int n;
int main(){
    while(scanf("%d", &n) != EOF)
    {
        mx = 0;
        v.clear();
        memset(mp, 0, sizeof(mp));
        for(int i = 1; i <= n; i++){
            scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].v);
            //mx = max(mx, a[i].r);
            v.push_back(a[i].l);
            v.push_back(a[i].r);
        }
        sort(a + 1, a + n + 1);
        sort(v.begin(), v.end()), v.erase(unique(v.begin(), v.end()), v.end());
        mx = (int)v.size();
        for(int i = 1; i <= n; i++){
            long long dp = query(getid(a[i].l));
            update(getid(a[i].r), dp + a[i].v);
        }
        printf("%lld\n", query(mx));
    }
    return 0;
}

代码2 : unorder_map

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 5;
unordered_map<int, LL> c;
struct Line
{
    int l, r, v;
} line[maxn];
int maxm;
int lowbit(int x)
{
    return x & -x;
}
void Modify(int pos, LL x)
{
    for (int i = pos; i <= maxm; i += lowbit(i))
        c[i] = max(c[i], x);
}
LL GetMax(int pos)
{
    LL ret = 0;
    for (int i = pos; i > 0; i -= lowbit(i))
        ret = max(ret, c[i]);
    return ret;
}
struct FastIO
{
    static const int S = 1310720;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar()
    {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos ++];
    }
    inline int xuint()
    {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos ++] = x;
    }
    inline void wint(LL x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n ++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
int main()
{
    int n;
    while (true)
    {
        n = io.xuint();
        maxm = 0;
        c.clear();
        for (int i = 1; i <= n; i++)
        {
            line[i].l = io.xuint();
            line[i].r = io.xuint();
            line[i].v = io.xuint();
            maxm = max(maxm, line[i].r);
        }
        sort(line + 1, line + 1 + n, [](Line & x, Line & y)
        {
            if (x.r == y.r)
                return x.l < y.l;
            else return x.r < y.r;
        });
        for (int i = 1; i <= n; i++)
        {
            LL dp = GetMax(line[i].l);
            Modify(line[i].r, dp + line[i].v);
        }
        io.wint(GetMax(maxm));
        io.wchar('\n');
    }
    return 0;
}

代码3:动态开点线段树

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long LL;
struct Line
{
    int l, r, v;
} line[maxn];
const int maxm = 4e6;
int lson[maxm], rson[maxm];
LL mx[maxm];
int clk;
void init()
{
    lson[0] = rson[0] = mx[0] = 0;
    clk = 0;
}
int newnode()
{
    clk++;
    lson[clk] = rson[clk] = mx[clk] = 0;
    return clk;
}
void Modify(int &id, int L, int R, int pos, LL val)
{
    if(id == 0) id = newnode();
    if(L == R) mx[id] = max(mx[id], val);
    else
    {
        int mid = L + R >> 1;
        if(pos <= mid) Modify(lson[id], L, mid, pos, val);
        else Modify(rson[id], mid + 1, R, pos, val);
        mx[id] = max(mx[lson[id]], mx[rson[id]]);
    }
}
LL GetMax(int id, int L, int R, int l, int r)
{
    if(id == 0) return 0;
    if(l <= L && R <= r) return mx[id];
    else
    {
        LL ret = 0;
        int mid = L + R >> 1;
        if(l <= mid) ret = max(ret, GetMax(lson[id], L, mid, l, r));
        if(mid < r) ret = max(ret, GetMax(rson[id], mid + 1, R, l, r));
        return ret;
    }
}
int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        int st = INT_MAX, en = -INT_MAX;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d %d %d", &line[i].l, &line[i].r, &line[i].v);
            st = min(st, line[i].l);
            en = max(en, line[i].r);
        }
        sort(line + 1, line + 1 + n, [](Line & x, Line & y)
        {
            if(x.r == y.r)
                return x.l < y.l;
            else return x.r < y.r;
        });
        init();
        int rt = 0;
        for(int i = 1; i <= n; i++)
        {
            LL dp = GetMax(rt, st, en, st, line[i].l);
            Modify(rt, st, en, line[i].r, dp + line[i].v);
        }
        printf("%lld\n", mx[rt]);
    }
    return 0;
}

H: FM的孤独旅程
DP。dp[i][j]代表在i点当前经过了j个点的最小花费。我写标算的时候写了DFS,但是被hack机出了几组数据卡成了狗。
先上一下我的DFS代码

//这题会TLE。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005;
int dp[maxn][maxn], pre[maxn][maxn];//dp[i][j]代表在i点当前经过了j个点的最小花费
int n, m, T;
vector <int> E[maxn];
vector <int> val[maxn];
vector <int> ans;
void dfs(int x, int num, int cost, int fa)
{
    if(dp[x][num] <= cost) return;
    dp[x][num] = cost;
    pre[x][num] = fa;
    for(int i = 0; i < (int)E[x].size(); i++)
    {
        if(cost + val[x][i] <= T)
        {
            dfs(E[x][i], num+1, cost+val[x][i], x);
        }
    }
}
void print_path(int x, int y)
{
    ans.push_back(x);
    if(pre[x][y] == -1)
    {
        cout << ans.size() << endl;
        for(int i = (int)(ans.size() - 1); i >= 0; i--) cout << ans[i] << " ";
        cout << endl;
        return ;
    }
    else
    {
        print_path(pre[x][y], y-1);
    }
}
int main()
{
    //freopen("5.in","r",stdin);
   // freopen("5.out","w",stdout);
    while(scanf("%d%d%d", &n, &m, &T) != EOF)
    {
        memset(pre, -1, sizeof(pre));
        for(int i = 0; i < maxn; i++)
        {
            for(int j = 0; j < maxn; j++)
            {
                dp[i][j] = 1e9+7;
            }
        }
        ans.clear();
        for(int i = 0; i < maxn; i++) E[i].clear(), val[i].clear();
        for(int i = 1; i <= m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            E[a].push_back(b);
            val[a].push_back(c);
        }
        dfs(1, 1, 0, -1);
        for(int i = n; i >= 2; i--)
        {
            if(dp[n][i] <= T)
            {
                printf("%d\n", dp[n][i]);
                print_path(n, i);
                break;
            }
        }
    }
    return 0;
}

当把DFS改成SPFA后,发现世界突然变快了100倍

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e3 + 5;
struct EDGE
{
    int to, next, len;
    EDGE(int to = 0, int next = 0, int len = 0): to(to), next(next), len(len) {}
} edge[maxn];
int head[maxn], edgecnt;
int dis[maxn][maxn];
int pre[maxn][maxn];
bool vis[maxn][maxn];
void init()
{
    memset(head, -1, sizeof(head));
    edgecnt = 0;
    memset(dis, 0x7F, sizeof(dis));
    memset(vis, 0, sizeof(vis));
}
void add(int s, int t, int l)
{
    edge[edgecnt] = EDGE(t, head[s], l);
    head[s] = edgecnt++;
}
int main()
{
    int n, m, t;
    while(~scanf("%d %d %d", &n, &m, &t))
    {
        init();
        while(m--)
        {
            int u, v, l;
            scanf("%d %d %d", &u, &v, &l);
            add(u, v, l);
        }
        dis[1][1] = 0;
        queue<pair<int, int> >q;
        q.push(make_pair(1, 1));
        while(!q.empty())
        {
            int u = q.front().first;
            int p = q.front().second;
            q.pop();
            vis[u][p] = 0;
            for(int i = head[u]; ~i; i = edge[i].next)
            {
                int v = edge[i].to;
                int tt = dis[u][p] + edge[i].len;
                if(dis[v][p + 1] > tt)
                {
                    dis[v][p + 1] = tt;
                    pre[v][p + 1] = u;
                    if(!vis[v][p + 1])
                    {
                        vis[v][p + 1] = 1;
                        q.push(make_pair(v, p + 1));
                    }
                }
            }
        }
        int ans;
        for(int i = n; i >= 1; i--)
            if(dis[n][i] <= t)
            {
                ans = i;
                break;
            }
        printf("%d\n%d\n", dis[n][ans], ans);
        stack<int>s;
        while(n != 1)
        {
            s.push(n);
            n = pre[n][ans];
            ans--;
        }
        s.push(1);
        while(!s.empty())
        {
            printf("%d ", s.top());
            s.pop();
        }
    }
    return 0;
}

I,不会做QAQ,题解找上决。。。。