*A.黑白边 *
为了让白边使用次数最小,可以先连全部的黑边再连白边。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
long long x = 0; bool s = 0; char ch = 0;
while (!isdigit(ch)) { s |= (ch == '-'); ch = getchar(); }
while (isdigit(ch)) { x = (x << 1) + (x << 3) + (ch - 48); ch = getchar(); }
return s ? -x : x;
}
struct node{
    int x,y,flag;
};
vector<node>g;
vector<node>v;
int vis[300000];
int tp(int s)
{
    if(s==vis[s])
    return s;
    return vis[s]=tp(vis[s]);
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    vis[i]=i;
    for(int i=1;i<=m;i++)
    {
          int q,w,e;
          cin>>q>>w>>e;
          if(e==0)
          g.push_back({q,w,e});
          else
          v.push_back({q,w,e});  
    }
    for(node k:g)
    {
      if(tp(k.x)!=tp(k.y))
      vis[tp(k.x)]=tp(k.y);
    }
    int ans=0;
    for(node k:v)
    {
        if(tp(k.x)!=tp(k.y))
        {
            vis[tp(k.x)]=tp(k.y);
            ans++;
        }
    }
    set<int>p;
    for(int i=1;i<=n;i++)
    {
     p.insert(tp(i));
    }
    if(p.size()==1)
    cout<<ans;
    else
    {
        cout<<-1;
    }

getchar();
getchar();
}

*B.最好的宝石 *
区间操作使用线段树,每个节点维护最大值和最大值的个数,对于区间合并分情况讨论,如果是两区间最大值相等,最大值个数就要相加,否则就是较大一方的最大值了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
    long long x = 0;
    bool s = 0;
    char ch = 0;
    while (!isdigit(ch))
    {
        s |= (ch == '-');
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch - 48);
        ch = getchar();
    }
    return s ? -x : x;
}
int a[600000];
struct node
{
    int l, r, mx, sum;
} g[800000];
typedef pair<int, int> p;
void build(int q, int x, int y)
{
    g[q].l = x;
    g[q].r = y;
    if (x == y)
    {
        g[q].mx = a[x];
        g[q].sum = 1;
        return;
    }
    int mid = x + y >> 1;
    build(q * 2, x, mid);
    build(q * 2 + 1, mid + 1, y);
    if (g[q * 2].mx == g[q * 2 + 1].mx)
    {
        g[q].mx = g[q * 2].mx;
        g[q].sum = g[q * 2].sum + g[q * 2 + 1].sum;
    }
    else if (g[q * 2].mx > g[q * 2 + 1].mx)
    {
        g[q].mx = g[q * 2].mx;
        g[q].sum = g[q * 2].sum;
    }
    else
    {
        g[q].mx = g[q * 2 + 1].mx;
        g[q].sum = g[q * 2 + 1].sum;
    }
}
p query(int q, int x, int y)
{
    p mx = make_pair(0, 0);
    if (x <= g[q].l && y >= g[q].r)
    {
        p k = make_pair(g[q].mx, g[q].sum);
        return k;
    }
    int mid = g[q].l + g[q].r >> 1;
    if (x <= mid)
    {
        p t1 = query(q * 2, x, y);
        if (t1.first > mx.first)
        {
            mx = t1;
        }
        else if (t1.first == mx.first)
        {
            mx.second += t1.second;
        }
    }
    if (y > mid)
    {
        p t2 = query(q * 2 + 1, x, y);
        if (t2.first > mx.first)
        {
            mx = t2;
        }
        else if (t2.first == mx.first)
        {
            mx.second += t2.second;
        }
    }
    return mx;
}
void change(int q, int x, int y)
{
    if (g[q].l == g[q].r && g[q].l == x)
    {
        g[q].mx = y;
        return;
    }
    int mid = g[q].l + g[q].r >> 1;
    if (x <= mid)
    {
        change(q * 2, x, y);
    }
    else
    {
        change(q * 2 + 1, x, y);
    }
    if (g[q * 2].mx == g[q * 2 + 1].mx)
    {
        g[q].mx = g[q * 2].mx;
        g[q].sum = g[q * 2].sum + g[q * 2 + 1].sum;
    }
    else if (g[q * 2].mx > g[q * 2 + 1].mx)
    {
        g[q].mx = g[q * 2].mx;
        g[q].sum = g[q * 2].sum;
    }
    else
    {
        g[q].mx = g[q * 2 + 1].mx;
        g[q].sum = g[q * 2 + 1].sum;
    }
}
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    build(1, 1, n);
    for (int i = 1; i <= m; i++)
    {
        string s;
        int  d, f;
        cin >> s >> d >> f;
        if (s == "Ask")
        {
            p k = query(1, d, f);
            cout << k.first << " " << k.second << "\n";
        }
        else
        {
            change(1, d, f);
        }
    }

    getchar();
    getchar();
}

C.滑板上楼梯
每次跳4格,3,1轮流跳

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
long long x = 0; bool s = 0; char ch = 0;
while (!isdigit(ch)) { s |= (ch == '-'); ch = getchar(); }
while (isdigit(ch)) { x = (x << 1) + (x << 3) + (ch - 48); ch = getchar(); }
return s ? -x : x;
}
int main()
{
    ll n;
    cin>>n;
    ll k=n%4;
    ll ans=n/4;
    if(k==3)
    cout<<ans*2+1;
    else
    cout<<ans*2+k;
getchar();
getchar();
}

*D.GCD *
把1-n的素数筛出来,结果为素数种类+1.时间复杂度n图片说明

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
    long long x = 0;
    bool s = 0;
    char ch = 0;
    while (!isdigit(ch))
    {
        s |= (ch == '-');
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch - 48);
        ch = getchar();
    }
    return s ? -x : x;
}
int a[500000];
int main()
{
    int n;
    cin >> n;
    for (int i = 2; i <= n; i++)
    {
        int k = i;
        for (int j = 2; j <= sqrt(i); j++)
        {
            if (k % j == 0)
            {
                while (k % j == 0)
                    k /= j;
                a[j]++;
            }
        }
        if (k > 1)
        {
            a[k]++;
        }

    }
    int mx = 0;
    int flag=0;
    for (int i = 2; i <= n; i++)
     {
         if(a[i])
         {
              mx++;
              if(a[i]>=2)
              flag=1;
         }

     }
     if(flag)
     cout<<mx+2;
     else
     {
         cout<<-1;
     }


    getchar();
    getchar();
}

*E.牛牛的加法 *
模拟,主要前导零

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
    long long x = 0;
    bool s = 0;
    char ch = 0;
    while (!isdigit(ch))
    {
        s |= (ch == '-');
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch - 48);
        ch = getchar();
    }
    return s ? -x : x;
}
string add(string a, string b)
{
    string s = "";
    int l = a.length() - 1;
    int r = b.length() - 1;
    while (l >= 0 && r >= 0)
    {
        int aa = a[l] - '0';
        int bb = b[r] - '0';
        aa = (aa + bb) % 10;
        s = (char)(aa + '0') + s;
        l--;
        r--;
    }
    while (l >= 0)
    {

        s = a[l] + s;
        l--;
    }
    while (r >= 0)
    {
        s = b[r] + s;
        r--;
    }
    return s;
}
int main()
{
    string a, b;
    cin >> a >> b;
    string k = add(a, b);
    while (k.length())
    {
        if (k[0] == '0')
            k.erase(0,1);
        else
        {
            break;
        }
    }
    if (k.length() == 0)
        cout << 0;
    else
    {
        cout << k;
    }

    getchar();
    getchar();
}

*F.石子合并 *
贪心,每次拿最大值和别人合并

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
long long x = 0; bool s = 0; char ch = 0;
while (!isdigit(ch)) { s |= (ch == '-'); ch = getchar(); }
while (isdigit(ch)) { x = (x << 1) + (x << 3) + (ch - 48); ch = getchar(); }
return s ? -x : x;
}
int a[400000];
int main()
{
    int n;
    cin>>n;
    int mx=0;
    int index=0;
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
     cin>>a[i];
     if(a[i]>mx)
     {
         mx=a[i];
         index=i;
     }
    }
    for(int i=1;i<=n;i++)
    {
        if(i!=index)
        sum+=(mx+a[i]);
    }
    cout<<sum;


getchar();
getchar();
}

G.滑板比赛
应该是双指针,这里用了二分。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
    long long x = 0;
    bool s = 0;
    char ch = 0;
    while (!isdigit(ch))
    {
        s |= (ch == '-');
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch - 48);
        ch = getchar();
    }
    return s ? -x : x;
}
vector<int> g;
int b[400000];
int main()
{
    int n, m;
    cin >> n >> m;
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        g.push_back(x);
    }
    for (int i = 1; i <= m; i++)
        cin >> b[i];
    sort(g.begin(), g.end());
    for (int i = 1; i <= m; i++)
    {

        int k = upper_bound(g.begin(), g.end(), b[i]) - g.begin();

        if (k < g.size())
        {
            ans++;
            g.erase(g.begin() + k);
        }
    }
    cout << ans;
    getchar();
    getchar();
}

*H.第 k 小 *
用最大堆维护前k小,后面没有就舍弃了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
    long long x = 0;
    bool s = 0;
    char ch = 0;
    while (!isdigit(ch))
    {
        s |= (ch == '-');
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch - 48);
        ch = getchar();
    }
    return s ? -x : x;
}
priority_queue<int> p;
int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
    {
        int w;
        cin >> w;
        p.push(w);
        if (p.size() > k)
            p.pop();
    }

    for (int i = 1; i <= m; i++)
    {
        int w;
        cin >> w;
        if (w == 1)
        {
            int e;
            cin >> e;
            p.push(e);
            if (p.size() > k)
                p.pop();
        }
        else
        {
            if(p.size()==k)
            cout << p.top() << "\n";
            else
            {
                cout<<"-1"<<"\n";
            }

        }
    }

    getchar();
    getchar();
}

*I.区间异或 *
时间复杂度On(nn+nm)发现暴力也能过。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[600000];
int dp[5000][5000];
int p[600000];
vector<int> g;
map<ll, int> vis;
inline long long read()
{
    long long x = 0;
    bool s = 0;
    char ch = 0;
    while (!isdigit(ch))
    {
        s |= (ch == '-');
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch - 48);
        ch = getchar();
    }
    return s ? -x : x;
}
int main()
{
    ll n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
       a[i]=read();
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = i; j <= n; j++)
        {
            dp[i][j] = dp[i][j - 1] xor a[j];  
            p[j-i+1] = max(p[j-i+1], dp[i][j]);
        }
    }
    sort(g.begin(), g.end());
    for (int i = 1; i <= m; i++)
    {
        int w;
       w=read();
       int flag=1;
       for(int j=1;j<=n;j++)
       {
           if(p[j]>=w)
           {
               flag=0;
               cout<<j<<"\n";
               break;
           }
       }
       if(flag)
       cout<<"-1"<<"\n";
    }

    getchar();
    getchar();
}

J.小游戏
dp
dp[i]=max(dp[i],max(dp[i-1],dp[i-2]+cnt[i]*i))

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline long long read()
{
    long long x = 0;
    bool s = 0;
    char ch = 0;
    while (!isdigit(ch))
    {
        s |= (ch == '-');
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch - 48);
        ch = getchar();
    }
    return s ? -x : x;
}
vector<ll> p;
ll cnt[300000];
ll v[300000];
ll dp[300000];
int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        ll w;
        cin>>w;
        cnt[w]++;
        if (!v[w])
        {
            v[w] = 1;
            p.push_back(w);
        }
    }
    sort(p.begin(), p.end());
    ll mx = 0;
    for (int i = 1; i <= 2e5; i++)
    {
        if (i == 1)
        {
            dp[i] = cnt[i];
            continue;
        }
        dp[i] = max(dp[i], max(dp[i - 1], dp[i - 2] + cnt[i] * i));
        mx = max(mx, dp[i]);
    }
    cout << mx;

    getchar();
    getchar();
}