刷题记录单

atcoder rating限制网站

8.19

D - Forbidden Difference

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
#define QWQ return 0;
const ll INF = 1e18;
const ll N = 1e6 + 10;
void solve()
{
    ll n, D;cin >> n >> D;
    vector<int>cnt(2000010, 0);
    if(!D)
    {
        set<int>s;
        for(int i = 1; i <= n ;i ++ ) 
        {
            int x;cin >> x;
            s.insert(x);
        }
        cout << n - s.size() << '\n';
        return;
    }
    for(int i = 1; i <= n; i ++ )
    {
        ll x;cin >> x;
        cnt[x] ++;
    }
    ll res{};
    for(int i = 0; i < D ;i ++ )
    {
        //(1e6 - i) / D
        vector<ll>dp((N - i) / D + 1, INF);
        dp[0] = 0;
        dp[1] = min(cnt[i + D], cnt[i]);
        for(int j = 2;  j <= (N - i) / D; j ++ )
        {
            dp[j] = min(dp[j - 1] + cnt[i + j * D], dp[j - 2] + cnt[i + (j - 1) * D]);
        }
        res += dp[(N - i) / D];
    }
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

D - Go Straigh

#include <bits/stdc++.h>
#include <iterator>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
#define QWQ return 0;
const ll INF = 1e18;
const ll N = 1e6 + 10;
void solve()
{
    ll n, m;cin >> n >> m;
    vector<string>g(n);
    pll S, T;
    for(int i = 0 ; i <n ; i ++ )
    {
        cin >> g[i];
        for(int j = 0 ;j < m; j ++ )
        {
            if(g[i][j] == 'S') S = make_pair((ll)i, (ll)j);
            if(g[i][j] == 'G') T = make_pair((ll)i, (ll)j);
        }
    }
    auto code = [&](int x, int y, int dir)->ll {return (x * 1000 + y) * 4 + dir;};
    auto decode = [&](ll code)->array<int, 3>
    {
        int x, y, dir;
        dir = code % 4;
        y = code / 4 % 1000;
        x = code / 4 / 1000;
        return {x, y, dir};
    };
    queue<ll>q;
    // for(int i = 0 ;i < 4; i ++ ) q.emplace(code(S.first, S.second, i));
    q.emplace(code(S.first, S.second, 0));
    vector<bool>vis((1000 * 1000 + 1) << 2);
    vis[code(S.first, S.second, 0)] = true;
    auto isok = [&](int x, int y)->bool
    {
        if(x < 0 || y < 0 || x >= n || y >= m || g[x][y] == '#') return false;
        return true;
    };
    vector<ll>fa((1000 * 1000 + 1) << 2, -1);

    // int cnt = 0;
    const string Dir = "URDL";

    while(!q.empty())
    {
        ll c = q.front();q.pop();
        array<int, 3> u = decode(c);
        if(u[0] == T.first && u[1] == T.second)
        {
            string res;
            while(~fa[c])
            {
                res += Dir[c % 4];
                c =fa[c];
            }
            reverse(res.begin(), res.end());
            cout << "Yes\n";
            cout << res << '\n';
            return;
        }
        // if(cnt ++ >= 100) return;
        // cout << "TEST : " << u[0] << " " << u[1] << '\n';
        int nx[] = {u[0] - 1, u[0], u[0] + 1, u[0]};
        int ny[] = {u[1], u[1] + 1, u[1], u[1] - 1};
        if(g[u[0]][u[1]] == 'o')
        {
            if(isok(nx[u[2]], ny[u[2]]))
            {
                if(vis[code(nx[u[2]], ny[u[2]], u[2])]) continue;
                vis[code(nx[u[2]], ny[u[2]], u[2])] = true;
                fa[code(nx[u[2]], ny[u[2]], u[2])] = c;
                q.emplace(code(nx[u[2]], ny[u[2]], u[2]));
            }
            continue;
        } 
        for(int i = 0 ;i < 4; i ++ )
        {
            if(g[u[0]][u[1]] == 'x' && i == u[2]) continue;
            int x= nx[i], y = ny[i];
            if(!isok(x, y)) continue;
            if(vis[code(x, y, i)]) continue;
            vis[code(x, y, i)] = true;
            fa[code(x, y, i)] = c;
            q.emplace(code(x, y, i));
        }
    }
    cout << "No\n";
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

E - Sum of Subarrays

可认为是给定区间 \([L,R]\),它的所有子区间和的和就是

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
#define QWQ return 0;

void solve()
{
	int n,q;cin >> n >> q;
	vector<ll>a(n + 1);
	for(int i = 1; i <= n ;i ++ ) cin >> a[i];
	vector<ll>pre(n + 1), prej(n + 1),prej2(n + 1);
	for(int i = 1; i <= n ;i ++ ) 
	{
		pre[i] = pre[i - 1] + a[i];
		prej[i] = prej[i - 1] + a[i] * i;
		prej2[i] = prej2[i - 1] + a[i] * i * i;
	}
	while(q -- )
	{
		ll l, r;cin >> l >> r;
		cout << (r + l) * (prej[r] - prej[l - 1]) - (prej2[r] - prej2[l - 1]) + (1 - l - l * r + r) * (pre[r] - pre[l - 1]) << '\n';
	}
}
int main()
{
	cin.tie(0)->ios::sync_with_stdio(false);
	int _ = 1;
	while( _ -- ) solve();
	QWQ	
}

import sys

n, q = map(int, sys.stdin.readline().split())
a = list(map(int, sys.stdin.readline().split()))
pre = [0] * (n + 1)
prei = [0] * (n + 1)
prei2 = [0] * (n + 1)
for i in range(1, n + 1) : 
    pre[i] = pre[i - 1] + a[i - 1]
    prei[i] = prei[i - 1] + a[i - 1] * i
    prei2[i] = prei2[i - 1] + a[i - 1] * i * i
for _ in range(q) : 
    l, r = map(int, sys.stdin.readline().split())
    # print("TEST : ", l ,r)
    res = 0
    res += (l + r) * (prei[r] - prei[l - 1])
    res += -(prei2[r] - prei2[l - 1])
    res += (1 - l - l * r + r) * (pre[r] - pre[l - 1])
    print(res)

8.20

D - KAIBUNsyo

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
void solve()
{
    int n;cin >> n;
    vector<int>a(n);
    vector<int>cnt(200000 + 10 , 0);
    vector<int>P;
    for(int i = 0 ;i < n ;i ++ )
    {
        cin >> a[i];
        if(!cnt[a[i]]) P.emplace_back(a[i]);
        cnt[a[i]] ++;
    }
    vector<vector<int>>g(200000 + 1);
    for(int i = 0 ;i < n / 2; i ++ )
    {
        g[a[i]].emplace_back(a[n - i - 1]);
        g[a[n - i - 1]].emplace_back(a[i]);
    }
    vector<bool>vis(200000 + 10, false);
    ll res{};
    queue<int>q;
    auto bfs = [&](int start)->void
    {
        ll c{};
        q.emplace(start);
        while(!q.empty())
        {
            int u = q.front();q.pop();
            if(vis[u]) continue;
            vis[u] = true;
            c ++ ;
            for(int v : g[u])
            {
                q.emplace(v);
            }
        }
        res += c - 1;
    };
    for(int& v : P)
    {
        if(vis[v]) continue;
        bfs(v);
    }
    cout << res << '\n';
}
int main()
{
	cin.tie(0)->ios::sync_with_stdio(false);
	int _ = 1;
	while( _ -- ) solve();
	QWQ	
}

D - Shortest Path Queries 2

居然是floyd
很少见捏

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
constexpr ll INF = 1e18;
void solve()
{
    int n, m;cin >> n >> m;
    //floyd
    //dp[i][j][k] = min(dp[i][j][k - 1], dp[i][k][k - 1] + dp[k][j][k - 1])
    vector<vector<ll>>dp(n + 1, vector<ll>(n + 1, INF));
    for(int i = 0 ;i < m ;i ++ )
    {
        int u, v, w;cin >> u >> v >> w;
        dp[u][v] = w;
    }
    for(int i = 1 ;i <= n ;i ++ ) dp[i][i] = 0;
    ll res{};
    for(int k = 1; k <= n ;k ++ )
    {
        for(int i = 1 ; i<= n ; i ++ )
        {
            for(int j = 1; j <= n ;j ++ )
            {
                dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
            }
        }
        for(int i = 1 ; i<= n; i ++ ) for(int j = 1 ;j <= n ; j ++ )
        {
            if(dp[i][j] == INF) continue;
            res += dp[i][j];
        }
    }
    cout << res << '\n';
}
int main()
{
	cin.tie(0)->ios::sync_with_stdio(false);
	int _ = 1;
	while( _ -- ) solve();
	QWQ	
}

py版本

import sys
INF = 1000000000000000000
n, m = map(int, sys.stdin.buffer.readline().split())
# dp = [[INF] * (n + 1)] * (n + 1)
# 这么写会出bug,导致所有操作都在同一列上
# emmmm在py中你[] * (n + 1)这样是创建一个n + 1的列表中每一个列表的指针都指向[]中的元素
# [0] * (n + 1)可生效的原因是在于整数是不可变对象,在赋值的时候他会去移动指针创建新的int
#所以其实还有写法如
dp = [ [INF] * (n + 1) for _ in range(n + 1)]
#dp = [[INF for _ in range(n + 1)] for _ in range(n + 1)]
for _ in range(m) : 
    u, v, w = map(int, sys.stdin.buffer.readline().split())
    dp[u][v] = w
for i in range(1, n + 1) : dp[i][i] = 0
res = 0
for k in range(1, n + 1) : 
    for i in range(1, n + 1) : 
        for j in range(1, n + 1) : 
            dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])
            # print("TEST : " , dp[i][j])
    for i in range(1, n + 1) : 
        for j in range(1, n + 1) :
            if dp[i][j] == INF : continue
            res += dp[i][j]
print(res)

dp练习ing

I - Coins

import sys

INF = 1000000000000000000
n = int(input())
p = list(map(float, sys.stdin.readline().split()))
dp = [[0.0] * 3000 for _ in range(n + 1)]
# print(p)
dp[1][1] = p[0]
dp[1][0] = 1.00000000000 - p[0]
for i in range(2, n + 1) :
    dp[i][0] = dp[i - 1][0] * (1 - p[i - 1]) 
    for j in range(1, i + 1) : 
        dp[i][j] = dp[i - 1][j - 1] * p[i - 1] + dp[i - 1][j] * (1 - p[i - 1])
res = 0.0
for i in range(n // 2 + 1, n + 1) : 
    res += dp[n][i]
print("{:.10f}".format(res))

J - Sushi

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
constexpr ll INF = 1e18;
double dp[301][301][301];
bool st[301][301][301];
int n;
double dfs(int c1, int c2, int c3)
{
    int s = c1 + c2 + c3;
    if(!s) return 0;
    if(st[c1][c2][c3]) return dp[c1][c2][c3];
    double res = (double)n / s;
    if(c1 - 1>= 0) res += dfs(c1 - 1, c2, c3) * c1 / (double)s;
    if(c2 - 1>= 0) res += dfs(c1 + 1, c2 - 1, c3) * c2 / (double)s;
    if(c3 - 1>= 0) res += dfs(c1, c2 + 1, c3 - 1) * c3 / (double)s;
    st[c1][c2][c3] = true;
    return dp[c1][c2][c3] = res;  
}
void solve()
{
    cin >> n;
    array<int, 3>c{};
    for(int i = 0 ;i < n ;i ++ )
    {
        int x;cin >> x;
        c[x - 1] ++;
    }
    cout << fixed << setprecision(12) << dfs(c[0], c[1], c[2]) << '\n';
}
int main()
{
	cin.tie(0)->ios::sync_with_stdio(false);
	int _ = 1;
	while( _ -- ) solve();
	QWQ	
}

py栈递归太慢被t了

import sys

INF = 1000000000000000000
n = int(input())
a = list(map(int, sys.stdin.readline().split()))
a = [0] + a
c1, c2, c3 = 0, 0, 0
for i in range(1, n + 1) :
    c1 += a[i] == 1
    c2 += a[i] == 2
    c3 += a[i] == 3
dp = [[[0.0] * (n + 1) for _ in range(n + 1)] for _ in range(n + 1)]
st = [[[False] * (n + 1) for _ in range(n + 1)] for _ in range(n + 1)]
# dp[0][0][0] = 0
# for i in range(c1 + 1) : 
#     for j in range(c2 + 1) :
#         for k in range(c3 + 1) :
#             s = i + j + k
#             if s == 0 : continue
#             dp[i][j][k] = n / s
#             if i - 1 >= 0 : dp[i][j][k] += dp[i - 1][j][k] * i / s
#             if i + 1 <= c1 and j - 1 >= 0 : dp[i][j][k] += dp[i + 1][j - 1][k] * j / s
#             if j + 1 <= c2 and k - 1 >= 0 : dp[i][j][k] += dp[i][j + 1][k - 1] * k / s
st[0][0][0] = True
def dfs(cur1, cur2, cur3) : 
    s = cur1 + cur2 + cur3
    if st[cur1][cur2][cur3] : return dp[cur1][cur2][cur3]
    if s == 0 : return 0.0
    res = n / s
    if cur1 - 1 >= 0 : res += dfs(cur1 - 1, cur2, cur3) * cur1 / s
    if cur2 - 1 >= 0 : res += dfs(cur1 + 1, cur2 - 1, cur3) * cur2 / s
    if cur3 - 1 >= 0 : res += dfs(cur1, cur2 + 1, cur3 - 1) * cur3 / s
    st[cur1][cur2][cur3] = True
    dp[cur1][cur2][cur3] = res
    return res

print(dfs(c1, c2 , c3))

8.21

D - Cooking

emmm写是写出来了不过时间超25min了QAQ

import sys

n = int(input())
a = list(map(int ,sys.stdin.readline().split()))
sum = 0
st = [[False] * (100000 + 1) for _ in range(101)]#注意一下这里开数组一定要这么开不然的话双for太慢了会被t
dp = [[0] * (100000 + 1) for _ in range(101)]
for v in a : sum += v
def dfs(x = 0, cur1 = 0) : 
    if st[x][cur1] : return dp[x][cur1] 
    if x == n : return max(cur1, sum - cur1)
    res = min(dfs(x + 1, cur1 + a[x]), dfs(x + 1, cur1))
    dp[x][cur1] = res
    st[x][cur1] = True
    return res
print(dfs())

一开始还担心数组开这么大是不是会寄,但实际上没问题

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define QWQ return 0;
int dp[101][100010]{};
bool st[101][100010]{};
int n;
int sum{};
int dfs(vector<int>&a, int x = 0, int cur1 = 0)
{
    if(x == n) return max(sum - cur1, cur1);
    if(st[x][cur1]) return dp[x][cur1];
    st[x][cur1] = true;
    dp[x][cur1] = min(dfs(a, x + 1, cur1 + a[x]), dfs(a, x + 1, cur1));
    return dp[x][cur1];
}
void solve()
{
    cin >> n;
    vector<int>a(n);
    for(int i = 0 ;i < n ;i ++ )
    {
        cin >> a[i];
        sum += a[i];
    }
    cout << dfs(a) << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}
// 64 位输出请用 printf("%lld")

D - aab aba baa

一开始担心爆ll所以直接用py写了

import sys

def C(n, m) : 
    res = 1
    for i in range(n - m + 1, n + 1) : res *= i
    for i in range(1, m + 1) : res //= i
    return res
a, b, k = map(int, sys.stdin.readline().split())
def find(cur1 = a, cur2 = b, tar = k) : 
    if cur1 == 0 : return "b" * cur2
    if cur2 == 0 : return "a" * cur1
    res = ""
    t = C(cur1 + cur2 - 1, cur1 - 1)
    if t >= tar : 
        res += 'a' + find(cur1 - 1, cur2, tar)
    else :
        res += 'b' + find(cur1, cur2 - 1, tar - t) 
    return res

print(find())

但实际上cpp也能过,算排列组合的时候直接用地推算这样就不会爆ll了

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define QWQ return 0;
ll dp[31][31]{};
ll a, b, k;
string dfs(ll cur1 = a, ll cur2 = b, ll tar = k)
{
    if(!cur1) return string(cur2, 'b');
    if(!cur2) return string(cur1, 'a');
    ll t = dp[cur1 - 1][cur2];
    if(t >= tar) return 'a' + dfs(cur1 - 1, cur2, tar);
    else return 'b' + dfs(cur1, cur2 - 1, tar - t);
}
void solve()
{
    cin >> a >> b >> k;
    dp[0][0] = 1;
    for(int i = 0 ; i <= 30 ;i ++ ) for (int j = 0 ;j <= 30 ;j ++ )
    {
        if(i - 1 >= 0) dp[i][j] += dp[i - 1][j];
        if(j - 1 >= 0) dp[i][j] += dp[i][j - 1];
    }
    cout << dfs() << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}
// 64 位输出请用 printf("%lld")

8.22

E - Unique Color

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
#define QWQ return 0;
vector<int>c;
vector<vector<int>>g;
vector<int>cnt(100010, 0);
vector<int>res;
vector<bool>vis;
void dfs(int x)
{
    if(vis[x]) return;
    vis[x] = true;
    if(!cnt[c[x]]) res.emplace_back(x);
    cnt[c[x]] ++;
    for(int v : g[x]) dfs(v);
    cnt[c[x]] --;
}
void solve()
{
    int n;cin >> n;
    c.resize(n + 1);
    vis.resize(n + 1);
    for(int i = 1; i <= n;i ++ ) cin >> c[i];
    g.resize(n + 1);
    for(int i = 1 ; i <= n - 1;i ++ )
    {
        int u, v;cin >> u >> v;
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }
    //如果给的是一张图,那还要bfs取出树
    dfs(1);
    sort(res.begin(),res.end());
    for(int i = 0 ;i < res.size() ;i ++ ) cout << res[i] << '\n';
}

int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}
// 64 位输出请用 printf("%lld")

python版本

import sys
sys.setrecursionlimit(100010)
#emmm其中py默认递归深度是1000,再大就就会爆栈了,这里要设置一下
n = int(input())
c = list(map(int, sys.stdin.readline().split()))
c = [0] + c
g = [[] for _ in range(n + 1)]
for _ in range(n - 1) :
    u, v = map(int , sys.stdin.readline().split())
    g[u].append(v)
    g[v].append(u)
vis = [False] * (n + 1)
cnt = [0] * 100010
res = []
def dfs(x) : 
    if vis[x] : return
    vis[x] = True
    if not cnt[c[x]] :
        res.append(x)
    cnt[c[x]] += 1
    for v in g[x] : 
        dfs(v)
    cnt[c[x]] -= 1
dfs(1)
res.sort()
for v in res : 
    print(v)

C - ORXOR

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
#define QWQ return 0;
vector<int>a;
int n;
int dfs(int x = 0, int pre = 0, int cres = 0)
{
    // cout << "TEST : " << pre << " " << cres << '\n';
    if(x == n)
    {
        return pre ^ cres;
    }
    return min(dfs(x + 1, 0, cres ^ (pre | a[x])), dfs(x + 1, pre | a[x], cres));
}
void solve()
{
    cin >> n;
    a.resize(n);
    for(int i = 0; i < n ;i ++ ) cin >> a[i];
    cout << dfs() << '\n';
}
//contiguous intervals
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

py版本

import sys
sys.setrecursionlimit(21)
n = int(input())
a = list(map(int , sys.stdin.readline().split()))
def dfs(x = 0, pre = 0, cres = 0) : 
    if x == n : return pre ^ cres
    return min(dfs(x + 1, 0, cres ^ (pre | a[x])), dfs(x + 1, pre | a[x], cres))
print(dfs())

8.23

补一下之前的abc

A - A

import sys

def main() :
    s = sys.stdin.readline().strip()
    res = ""
    for i in range(len(s)) : 
        if s[i] != 'A' : 
            res += '.'
        else : 
            res += 'A'
    print(res)


if __name__ == "__main__" : main()

B - Break a Stick

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
#define QWQ return 0;
constexpr ll INF = 1e18;
void solve()
{
    int n;cin >> n;
    vector<int>L(n + 1);
    for(int i = 1 ; i<= n; i ++ ) cin >> L[i];
    vector<ll>pre(n + 1);
    for(int i = 1; i <= n ;i ++ ) pre[i] = pre[i - 1] + L[i];
    ll res = INF;
    for(int i = 1; i <= n - 1;i ++ )
    {
        res = min(res, abs(pre[i] - (pre[n] - pre[i])));
    }
    cout << res << '\n';
}
// from one end.
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

C - On a Diet

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
#define QWQ return 0;
constexpr ll INF = 1e18;
void solve()
{
    ll n, m, k;cin >> n >> m >> k;
    vector<ll>a(n + 1);
    vector<ll>pre(n + 1, 0);
    for(int i = 1; i <= n ;i ++ ) cin >> a[i];
    for(int i = 1; i <= n ;i ++ ) pre[i] = pre[i - 1] + a[i];
    ll sum{};
    vector<bool>vis(n + 1,false);
    for(int i = 1 ;i <= n ;i ++ ) 
    {
        if(i - m >= 1 && vis[i - m])
        {
            sum -= a[i - m];
        }
        if(sum + a[i] <= k)
        {
            sum += a[i];
            vis[i] = true;
            cout << "Yes\n";
        } 
        else cout << "No\n";
    }
}
// calorie
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

D - Bomber Mad

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
constexpr ll INF = 1e18;

void solve()
{
    int n,m, k;cin >> n >> m >> k;
    vector<string>g(n);
    for(int i = 0; i < n; i ++ ) cin >> g[i];
    
    vector<pll>safe;
    vector<bool>row(n, true),col(m,true);
    for(int i = 0 ;i < n ;i ++ )
    {
        bool fl = true;
        for(int j = 0 ;j < m ;j ++ ) if(g[i][j] == '#') fl = false;
        row[i] = fl;
    }
    for(int j = 0 ;j < m; j ++ )
    {
        bool fl = true;
        for(int i = 0 ;i < n ;i ++ ) if(g[i][j] == '#') fl = false;
        col[j] = fl;
    }

    // cout << "TEST : ";
    // for(int i = 0 ;i < n ;i ++ ) cout << row[i] << " ";
    // cout << "\n";

    // cout << "TEST : ";
    // for(int i = 0 ;i < m ;i ++ ) cout << col[i] << " ";
    // cout << "\n";


    queue<pii>q;
    ll res{};
    vector<vector<bool>>vis(n, vector<bool>(m, false));
    vector<vector<int>>dis(n, vector<int>(m, 0x3f3f3f3f));
    for(int i = 0 ; i < n ;i ++ ) for(int j = 0 ;j < m ;j ++ )
    {
        if(!row[i] || !col[j]) continue;
        q.emplace(i, j);
        dis[i][j] = 0;
        vis[i][j] = true;
        res ++;
    }
    while(!q.empty())
    {
        pii u = q.front();q.pop();
        for(int i = 0 ;i < 4; i ++ )
        {
            int nx[] = {u.first - 1, u.first, u.first + 1, u.first};
            int ny[] = {u.second, u.second + 1, u.second, u.second - 1};
            int x = nx[i], y = ny[i];
            if(x < 0 || y < 0 || x >= n ||y >= m ) continue;
            if(vis[x][y]) continue;
            vis[x][y] = true;
            if(g[x][y] == '#') continue;
            dis[x][y] = dis[u.first][u.second] + 1;
            if(dis[x][y] <= k) res ++;
            q.emplace(x, y);
        }
    }
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

E - Odd Cycle

原来resize不能重置元素啊,必须用assign才行,悲伤了

#include <bits/stdc++.h>
#include <cstdio>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
constexpr ll INF = 1e18;


vector<int>col;
vector<bool>tag;
int stk[200010]{}, tt = -1;
bool fl{}, nd{};

struct E
{
    int ne, v;
}e[200010 << 1];
int idx = 0;
vector<int>h;

void add(int u, int v)
{
    e[idx].v = v, e[idx].ne = h[u],h[u] = idx ++;
}
void dfs(vector<int>&res,int x, int pre)
{
    stk[++ tt] = x;
    for(int i = h[x]; ~i ; i = e[i].ne)
    {
        int v = e[i].v;
        if(i == (pre ^ 1)) continue;
        // cout << "TESt : " << x << " " << v << '\n';
        if(~col[v])
        {
            if(!fl && !nd && col[v] == col[x] && v != x)
            {
                fl = true;
                nd = true;
                // cout << "TEST : " << stk[tt] << '\n';
                res.emplace_back(stk[tt --]);
                tag[v] = true;
                return;
            }
            continue;
        }
        // cout << "TESt : " << v << " " << col[v] << " " << x << " " << col[x] << '\n';
        col[v] = col[x] ^ 1;
        dfs(res, v, i);
        if(fl)
        {
            if(nd) res.emplace_back(stk[tt]);
            if(tag[stk[tt]]) nd = false;
            tt --;
            return;
        }
    }
    tt --;
}
//
void solve()
{
    int n, m;cin >> n >> m;
    h.assign(n + 1, -1);
    col.assign(n + 1, -1);
    tag.assign(n + 1, false);
    fl = nd = false;
    idx = 0;
    for(int i = 0 ;i < m ;i ++ )
    {
        int u, v;cin >> u >> v;
        // cout << "TEST : " << u << " " << v << '\n';
        add(u, v);
        add(v, u);
    }
    vector<int>res;
    col[1] = 1;
    tt = -1;
    dfs(res, 1, -1);

    if(res.empty()) cout << -1 << '\n';
    else
    {
        cout << res.size() << '\n';
        for(int i = 0 ;i < res.size() ;i ++ ) cout << res[i] << " \n"[i == res.size() - 1];
    }
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;cin >> _;
    while( _ -- ) solve();
    QWQ
}

D - Opposite

公式法

#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
ld PI = acos(-1);
void solve()
{
    int n;cin >> n;
    ld theta = 2 * PI / (ld)n;
    ld x0, y0;cin >> x0 >> y0;
    ld x2, y2;cin >> x2 >> y2;
    ld midx = (x0 + x2) / 2, midy = (y0 + y2) / 2;
    //x = x2 + (x0 - x2)cos - (y0 - y2)sin
    //y = y2 + (x0 - x2)sin - (y0 - y2)cos
    ld x = midx + (x0 - midx) * cos(theta) - (y0 - midy) * sin(theta);
    ld y = midy + (x0 - midx) * sin(theta) + (y0 - midy) * cos(theta);
    cout <<fixed << setprecision(12) <<  x << " " << y << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

函数极角法

import sys
from math import atan2
from math import pi
from math import sqrt
from math import cos
from math import sin
def main() :
    n = int(input())
    x0, y0 = map(int, sys.stdin.readline().split())
    x2, y2 = map(int, sys.stdin.readline().split())
    mx = (x0 + x2)/ 2
    my = (y0 + y2)/ 2
    dx = x0 - mx
    dy = y0 - my
    r = sqrt(dx * dx + dy * dy)
    theta = atan2(dy, dx)
    theta += (2 * pi) / n
    x = mx + r * cos(theta)
    y = my + r * sin(theta)
    print(x, y)
if __name__ == "__main__" : main()

8.24

A. Hot Potatoes at the Fairy Warehouse

零和博弈、正和博弈、负和博弈:指博弈最终收益情况(你死我活,合作共赢,两败俱伤)
公平博弈:指的是双方拥有一样的信息和机会

思考传递土豆时候自己的收益
如果不是最后一轮的时候传递
那么传下去以后,原本后面那个会得到得分的机会
而前面那个人也会得到得分的机会

那么对于0101这样的第一个1呢(后面没人,前面队友堵着)
发现其实这种情况下先传递和最后传递收益是一样的
所以最终最优策略就是拖到最后再传

#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
// ld PI = acos(-1);
pii stk[100010];
int tt = -1;
void solve()
{
    int n, k;cin >> n >> k;
    string s;cin >> s;
    int c1{}, c2{};
    int p1{}, p2{};
    for(int i = 0 ;i < 2 * n ;i ++ )
    {
        if(s[i] == '1')
        {
            p1 += i & 1;
            p2 += !(i & 1);
        }
        if(s[i] == '1' && s[(i + 1) % (2 * n)] == '0')
        {
            c1 += !(i & 1);
            c2 += i & 1;
        }
    }
    // cout << "TEST : " << p1 << " " << p2 << " " << c1 << " " << c2 << '\n';
    cout << p1 + c1 - c2 << " " << p2 + c2 - c1 << '\n';
}   
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;cin >> _;
    while( _ -- ) solve();
    QWQ
}

C2. Marenol (hard version)

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
// ld PI = acos(-1);
pii stk[100010];
int tt = -1;
void solve()
{
    int n;cin >> n;
    string a, b;cin >> a >> b;
    a = '&' + a;
    b = '&' + b;
    vector<int>pa[2],pb[2];
    for(int i = 1; i <= n ; i ++ )
    {
        if(a[i] == '1') pa[i & 1].emplace_back(i);
        if(b[i] == '1') pb[i & 1].emplace_back(i);
    }

    if(pa[0].size() != pb[0].size() || pa[1].size() != pb[1].size())
    {
        cout << -1 << '\n';
        return;
    }
    ll res{};
    for(int i = 0 ;i < 2 ;i ++ )
    {
        for(int j = 0 ; j < pa[i].size(); j ++ )
        {
            res += abs(pa[i][j] - pb[i][j]) / 2;
        }
    }
    cout << res << '\n';
    // int c0{}, c1{};
    // for(int i = 1; i <= n ; i ++ )
    // {
    //     c0 += a[i] == '1' && !(i & 1);
    //     c1 += a[i] == '1' && (i & 1);
    //     c0 -= b[i] == '1' && !(i & 1);
    //     c1 -= b[i] == '1' && (i & 1);
    // }
    // if(c0 || c1)
    // {
    //     cout << -1 << '\n';
    //     return;
    // }
    // set<int>st1, st2;
    // for(int i = 1;i <= n ;i ++ )
    // {
    //     if(a[i] == '1')
    //     {
    //         if(i & 1) st1.insert(i);
    //         else st2.insert(i);
    //     }
    // }
    // ll res{};
    // for(int i = 1 ;i <= n ; i ++ )
    // {
    //     if(b[i] == '1')
    //     {
    //         if(i & 1)
    //         {
    //             auto it = st1.lower_bound(i);
    //             auto lar = it;
    //             if(it != st1.end())
    //             {
    //                 res  += abs(i - (*it)) / 2;
    //                 st1.erase(it);
    //                 continue;
    //             }
    //             -- it;
    //             res  += abs(i - (*it)) / 2;
    //             st1.erase(it);
    //         }
    //         else 
    //         {
    //             auto it = st2.lower_bound(i);
    //             auto lar = it;
    //             if(it != st2.end())
    //             {
    //                 res  += abs(i - (*it)) / 2;
    //                 st2.erase(it);
    //                 continue;
    //             }
    //             -- it;
    //             res  += abs(i - (*it)) / 2;
    //             st2.erase(it);
    //         }
    //     }
    // }
    // cout << res << '\n';
}   
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;cin >> _;
    while( _ -- ) solve();
    QWQ
}

C2. Marenol (hard version)

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
// ld PI = acos(-1);
pii stk[100010];
int tt = -1;
void solve()
{
    int n;cin >> n;
    string a, b;cin >> a >> b;
    a = '&' + a;
    b = '&' + b;
    vector<int>pa[2],pb[2];
    for(int i = 1; i <= n ; i ++ )
    {
        if(a[i] == '1') pa[i & 1].emplace_back(i);
        if(b[i] == '1') pb[i & 1].emplace_back(i);
    }

    if(pa[0].size() != pb[0].size() || pa[1].size() != pb[1].size())
    {
        cout << -1 << '\n';
        return;
    }
    ll res{};
    for(int i = 0 ;i < 2 ;i ++ )
    {
        for(int j = 0 ; j < pa[i].size(); j ++ )
        {
            res += abs(pa[i][j] - pb[i][j]) / 2;
        }
    }
    cout << res << '\n';
    // int c0{}, c1{};
    // for(int i = 1; i <= n ; i ++ )
    // {
    //     c0 += a[i] == '1' && !(i & 1);
    //     c1 += a[i] == '1' && (i & 1);
    //     c0 -= b[i] == '1' && !(i & 1);
    //     c1 -= b[i] == '1' && (i & 1);
    // }
    // if(c0 || c1)
    // {
    //     cout << -1 << '\n';
    //     return;
    // }
    // set<int>st1, st2;
    // for(int i = 1;i <= n ;i ++ )
    // {
    //     if(a[i] == '1')
    //     {
    //         if(i & 1) st1.insert(i);
    //         else st2.insert(i);
    //     }
    // }
    // ll res{};
    // for(int i = 1 ;i <= n ; i ++ )
    // {
    //     if(b[i] == '1')
    //     {
    //         if(i & 1)
    //         {
    //             auto it = st1.lower_bound(i);
    //             auto lar = it;
    //             if(it != st1.end())
    //             {
    //                 res  += abs(i - (*it)) / 2;
    //                 st1.erase(it);
    //                 continue;
    //             }
    //             -- it;
    //             res  += abs(i - (*it)) / 2;
    //             st1.erase(it);
    //         }
    //         else 
    //         {
    //             auto it = st2.lower_bound(i);
    //             auto lar = it;
    //             if(it != st2.end())
    //             {
    //                 res  += abs(i - (*it)) / 2;
    //                 st2.erase(it);
    //                 continue;
    //             }
    //             -- it;
    //             res  += abs(i - (*it)) / 2;
    //             st2.erase(it);
    //         }
    //     }
    // }
    // cout << res << '\n';
}   
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;cin >> _;
    while( _ -- ) solve();
    QWQ
}

D - Shipping Center

#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
ld PI = acos(-1);

vector<pii>c;
vector<int>sz;
int L, R;
int n, m, q;
void solve()
{
    cin >> n >> m >> q;
    c.resize(n + 1);
    sz.resize(m + 1);
    for(int i = 1 ;i <= n ;i ++ ) cin >> c[i].first >> c[i].second;
    for(int i = 1 ;i <= m ;i ++ ) cin >> sz[i];
    sort(c.begin() + 1, c.end(), [&](pii&x, pii&y)->bool{
        if(x.second != y.second) return x.second > y.second;
        return x.first > y.first;
    });
    while(q -- )
    {
        cin >> L >> R;
        ll mask{}, res{};
        vector<int>nd;
        for(int i = 1 ;i <= m; i ++ )
        {
            if(L <= i && i <= R) continue;
            nd.emplace_back(sz[i]);
        }
        sort(nd.begin(), nd.end());
        for(int stor : nd)
        {
            for(int j = 1; j <= n ;j ++ )
            {
                if(mask >> (j - 1) & 1) continue;
                if(stor >= c[j].first)
                {
                    mask |= 1LL << (j - 1);
                    res += c[j].second;
                    break;
                }
            }
        }
        cout << res << '\n';
    }
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

[D - Journey]

import sys

n = int(input())
res = 0
#E[x_0] = 0
for i in range(1, n) : 
    res += n / (n - i)
print(res)

8.25

E - Mex Min

emmmm头一次体会到stl中的multiset和set的超大常数
nlogn本来可以过,但是被卡常数了,用树状数组代替set即可

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
constexpr ll INF = 1000000000000000000LL;
struct BIT
{
    vector<int>a;int n;
    BIT(int x) : a(x + 10, 0), n(x){}
    void add(int x, int y)
    {
        while(x <= n)
        {
            a[x] += y;
            x += x & -x;
        }
    }
    ll query(int x)
    {
        ll res{};
        while(x)
        {
            res += a[x];
            x -= x & -x;
        }
        return res;
    }
};
ll lg(ll x){return 63 - __builtin_clzll(x);}
void solve()
{
    int n, m;cin >> n >> m;
    vector<int>a(n + 1);
    for(int i = 1 ; i <= n; i ++ )
    {
        cin >> a[i];
        a[i] ++;
    }
    BIT bit(n + 10);
    for(int i = 1; i <= n + 10;i ++ ) bit.add(i, 1);
    auto find = [&]()->ll
    {
        ll l = 1, r = n + 10;
        while(l < r)
        {
            int mid = l + r >>1;
            if(bit.query(mid) >= 1) r = mid;
            else l = mid + 1;
        } 
        return l;
    };
    vector<int>cnt(n + 10 , 0);
    for(int i = 1 ;i <= m ;i ++ )
    {
        if(!cnt[a[i]])bit.add(a[i], -1);
        cnt[a[i]] ++;
    }
    ll res = find() - 1;
    for(int i = m + 1;i <= n ;i ++ )
    {
        cnt[a[i - m]] --;
        if(!cnt[a[i - m]]) bit.add(a[i - m], 1);
        if(!cnt[a[i]]) bit.add(a[i] , -1);
        cnt[a[i]] ++;
        res = min(res, find() - 1);
    }
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

8.26

集训日,本来想复盘的但是没复盘多少QAQ
这里放几道值得之后复盘的题目

C - Intervals

#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <array>
#include <algorithm>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
constexpr ll INF = 1e18;
struct BIT
{
    vector<int>a;int n;
    BIT(int x) : a(x + 10 , 0) , n(x + 1){}
    void add(int x, int y)
    {
        while(x <= n)
        {
            a[x] += y;
            x += x & -x;
        }
    }
    ll query(int x)
    {
        if(x <= 0) return 0;
        ll res{};
        while(x)
        {
            res += a[x];
            x -= x & -x;
        }
        return res;
    }
    ll query_range(int l, int r)
    {
        return query(r) - query(l - 1);
    }
};
void solve()
{
    int n;cin >> n;
    vector<array<int, 3>>a(n);
    for(int i = 0 ;i < n ;i ++ )
    {
        cin >> a[i][0] >> a[i][1] >> a[i][2];
        a[i][0] ++;
        a[i][1] ++;
    }
    sort(a.begin(), a.end(), [&](array<int, 3>&x, array<int, 3>&y)->bool{
        return x[1] < y[1];
    });
    BIT bit(100000);
    vector<bool>vis(100000, false);
    for(int i = 0; i < n ;i ++ ) 
    {
        int l = a[i][0], r = a[i][1], c = a[i][2];
        int cnt = bit.query_range(l, r);
        int nd = c - cnt;
        int j = r;
        // cout << "TEST : " << l << " " << r << " " << c << '\n';
        // cout << "TEST : " << nd << '\n';
        // if(nd == 2) cout << "TEST : " << vis[8] << " " << vis[7] << '\n';
        while(nd > 0)
        {
            // if(l == 4 && r == 8)
            // {
            //     cout << "TEST :" << j << " " << vis[j] << '\n';
            // }
            if(j < l)
            {
                cout << "木有解\n ";
                return;
            }
            if(!vis[j])
            {
                vis[j] = true;
                bit.add(j, 1);
                nd --;
            }
            j --;
        }
    }
    cout << bit.query(100000) << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

D - To the Max

这道题虽然本身写法很暴力
但是让我想起了一些东西
比如说abc有原题他要求求出子矩阵和 == k的数量,这里我们就可以优化到\(O(n^3)\)了具体方法就是扫一个Up和Down
中间可以转化成求区间和 == k的区间数量,有两种方法一种是

  • 哈希表,\(pre[r] - pre[l - 1] = k\)即为对于每一个\(pre[r]\)去查一下前面\(pre[r] = pre[l - 1] + k\)的数量,可以用哈希表统计\(pre[l - 1] + k\)的数量
  • 双指针(有限制智能元素大于等于0)利用扩张单增的特性去滑动
    这里其实无非就是求区间和最大值
    这个我们可以用线段树实现
    线段树节点开个pre, suf,sum和mx,mx就是答案,更新就是
  • \(pre = max(L.pre, L.sum + R.pre)\)
  • \(suf = max(R.suf, R.sum + L.suf)\)
  • \(mx = max(pre, suf, R.pre + L.suf)\)
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
#define QWQ return 0;
constexpr ll INF = 1e18;
ll pre[110][110];
ll g[110][110];
ll Pre[110];
void solve()
{
    int n;cin >> n;
    for(int i = 1 ;i <= n ; i++ ) for(int j = 1 ; j <= n ; j ++ ) cin >> g[i][j];
    
    for(int i = 1; i <= n ;i ++ ) for(int j = 1; j <= n ;j ++ ) 
    {
        pre[j][i] = pre[j - 1][i] + g[i][j];
    }
    ll res = -INF;
    for(int U = 1; U <= n ; U ++ ) for(int D = U ; D <= n; D ++ )
    {
        memset(Pre, 0, sizeof Pre);
        for(int i = 1; i <= n ;i ++ ) Pre[i] = Pre[i - 1] + pre[D][i] - pre[U - 1][i];
        for(int i = 1; i <= n ;i ++ ) for(int j = i ;j <= n ;j ++ )
        {
            res = max(res, Pre[j] - Pre[i - 1]);
        }
    }
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

F - Distance in Tree

这题当时没开出来没想到二元统计的时候的乘法统计
这里的trick有点像是\(pre * a[i]\)来就算\(\sum a[i] * a[j]\)

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
struct E
{
    int ne, v;
}e[50001 << 1];
int h[50001], idx, n, k,res{}; 
void add(int u, int v){e[idx].v = v, e[idx].ne = h[u], h[u] = idx ++;}
int dp[50001][501];
void dfs(int u, int pre)
{

    for(int i = h[u]; ~i;i = e[i].ne)
    {
        if(pre == (i ^ 1)) continue;
        int v = e[i].v;
        dfs(v, i);
        //res += (dp[u][d]) * dp[v][k - d - 1];
        for(int j = 0 ;j < k ;j ++ )
        {
            res += dp[u][j] * dp[v][k - j - 1];//和pre * a[i]构造a[i] * a[j]一样的技巧
        }
        for(int j = 0; j < k ;j ++ ) dp[u][j + 1] += dp[v][j];
    }
}
void solve()
{
    memset(h, -1, sizeof h);
    cin >> n >> k;
    for(int i = 0 ;i < n - 1; i ++ )
    {
        int u, v;cin >> u >> v;
        add(u, v);
        add(v, u);
    }
    for(int i = 1 ;i <= n ;i ++ ) dp[i][0] = 1;
    dfs(1, -1);
    cout << res << '\n';
}   
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

G - Ksyusha and Chinchilla

基础的树形dp(虽然也不太像正经的树形dp),拿来练练手可以

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
// ld PI = acos(-1);

struct E
{
    int ne, v, id;
}e[200010 << 1];
int idx{}, fl{};
vector<int>h;
void add(int u, int v, int id)
{
    e[idx].v = v, e[idx].ne = h[u], e[idx].id = id, h[u] = idx ++;
}
vector<int>sz,res;
void dfs(int u, int pre)
{
    sz[u] = 1;
    for(int i = h[u]; ~i; i = e[i].ne)
    {
        if(i == (pre ^ 1)) continue;
        int v = e[i].v;
        dfs(v, i);
        sz[u] += sz[v]; 
    }
    if(sz[u] == 3)
    {
        sz[u] = 0;
        if(~pre)res.emplace_back(pre);
    }
    else if(sz[u] > 3) fl = false;
}
void solve()
{
    int n;cin >> n;
    h.assign(n + 1, -1);
    idx = 0;
    for(int i = 0 ;i < n - 1;i ++ )
    {
        int u, v;cin >> u >> v;
        add(u, v, i + 1);
        add(v, u, i + 1);
    }
    if(n % 3)
    {
        cout << -1 << '\n';
        return;
    }
    sz.assign(n + 1, 0);
    res.clear();
    res.reserve(n + 1);
    fl = true;
    dfs(1, -1);
    if(!fl)
    {
        cout << -1 << '\n';
        return;
    }
    cout << res.size() << '\n';
    for(int i = 0 ;i < res.size() ;i ++ )
    {
        cout << e[res[i]].id << ' ';
    }
    cout << '\n';
}   
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;cin >> _;
    while( _ -- ) solve();
    QWQ
}

8.27

复盘ing

D - Forbidden Difference25min内未完成QAQ
D - Go Straigh这个代码量问题,25min内未完成,但是差不多了
E - Sum of Subarrays完成
D - KAIBUNsyo换了一个写法
但是要注意dsu写的时候按秩合并不要写反了,不然会退化成\(O(n^2)\)(一开始不小心写反了一直t。QAQ)

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
// ld PI = acos(-1);
struct DSU
{
    vector<int>a,sz;
    DSU(int x) 
    {
        a.assign(x + 10, 0);
        sz.assign(x + 10 , 1);
        iota(a.begin(), a.end(), 0);
    }
    int find(int x)
    {
        while(a[x] != a[a[x]]) a[x] = a[a[x]];
        return a[x];
    }
    int size(int x){return sz[find(x)];}
    void merge(int x, int y)
    {
        x = find(x),y = find(y);
        if(sz[x] > sz[y]) swap(x, y);
        sz[y] += sz[x];
        a[x] = y;
    }
};
void solve()
{
    int n;cin >> n;
    vector<int>a(n + 1);
    for(int i = 1 ; i <= n ;i ++ ) cin >> a[i];
    DSU dsu(200010);
    for(int i = 1 ; i <= n / 2 ;i ++ ) dsu.merge(a[i], a[n - i + 1]);
    vector<int>tmp0,tmp1;
    tmp0.reserve(200001);
    tmp1.reserve(200001);
    for(int i = 1; i <= n ;i ++ ) tmp0.emplace_back(dsu.find(a[i]));
    sort(tmp0.begin(), tmp0.end());
    tmp0.erase(unique(tmp0.begin(), tmp0.end()), tmp0.end());
    for(int i = 1; i <= n ;i ++ ) tmp1.emplace_back(a[i]);
    sort(tmp1.begin(), tmp1.end());
    tmp1.erase(unique(tmp1.begin(), tmp1.end()), tmp1.end());
    cout << tmp1.size() - tmp0.size() << '\n';
}   
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

D - Shortest Path Queries 2完成,让我想起了bellmanford的限定走k步(不过这里是floyd)

8.28

复盘ing
I - Coins太久没用滚动数组了,用反了方向QAQ

import sys

INF = 1000000000000000000
n = int(input())
p = list(map(float, sys.stdin.readline().split()))
dp = [0.0] * 3001
# print(p)
dp[0] = 1
for i in range(1, n + 1) :
    for j in range(n, 0, -1) : 
        dp[j] = dp[j - 1] * p[i - 1] + dp[j] * (1 - p[i - 1])
    dp[0] = dp[0] * (1 - p[i - 1])
res = 0.0
for i in range((n + 2 - 1) // 2, n + 1) : 
    res += dp[i]
print("{:.10f}".format(res))

J - Sushi换个写法

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
int n;
double dp[301][301][301]{};
bool st[301][301][301]{};
void solve()
{
    cin >> n;
    int c1{},c2{},c3{};
    for(int i = 1; i <= n ;i ++ )
    {
        int x;cin >> x;
        c1 += x == 1;
        c2 += x == 2;
        c3 += x == 3;
    }
    //s = i + j + k;
    //dp[i][j][k] = 1 + dp[i][j][k] * (n - s) / n + dp[i - 1][j][k] * i / n + dp[i + 1][j - 1]][k] * j / n + dp[i][j + 1][k - 1] * k / n 
    //dp[i][j][k] = dp[i - 1][j][k] * i / s + dp[i + 1][j - 1]][k] * j / s + dp[i][j + 1][k - 1] * k / s
    // double res = dfs(cur1, cur2, cur3); 
    auto dfs = [&](auto&& dfs, int cur1, int cur2, int cur3)->double
    {
        int s = cur1 + cur2 + cur3;
        if(!s) return 0;
        if(st[cur1][cur2][cur3]) return dp[cur1][cur2][cur3];
        double res = n / (double)s;
        if(cur1 > 0) res += dfs(dfs, cur1 - 1, cur2, cur3) * cur1 / s;
        if(cur2 > 0) res += dfs(dfs, cur1 + 1, cur2 - 1, cur3) * cur2 / s;
        if(cur3 > 0) res += dfs(dfs, cur1, cur2 + 1, cur3 - 1) * cur3 / s;
        st[cur1][cur2][cur3] = true;
        return dp[cur1][cur2][cur3] = res;
    };
    cout << fixed << setprecision(10) << dfs(dfs,c1, c2, c3) << '\n';
}   

int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

D - Cooking完成
D - aab aba baa完成
A - A完成
B - Break a Stick完成
C - On a Diet完成
[D - Bomber Mad]完成
[E - Odd Cycle]完成,耗时50min有点长
E - Mex Min完成
还要稍微多考虑一下上界问题

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
// ld PI = acos(-1);
// struct DSU
// {
//     vector<int>a,sz;
//     DSU(int x) 
//     {
//         a.assign(x + 10, 0);
//         sz.assign(x + 10 , 1);
//         iota(a.begin(), a.end(), 0);
//     }
//     int find(int x)
//     {
//         while(a[x] != a[a[x]]) a[x] = a[a[x]];
//         return a[x];
//     }
//     int size(int x){return sz[find(x)];}
//     void merge(int x, int y)
//     {
//         x = find(x),y = find(y);
//         if(sz[x] > sz[y]) swap(x, y);
//         sz[y] += sz[x];
//         a[x] = y;
//     }
// };
// struct E
// {
//     int ne, v;
// }e[200001 << 1];
// int idx{};
// vector<int>h;
// void add(int u, int v) {e[idx].v = v,e[idx].ne = h[u], h[u] = idx ++;}
struct BIT
{
    vector<int>a;int n;
    BIT(int x) : n(x + 1), a(x + 10, 0){}
    void add(int x,int y)
    {
        while(x <= n)
        {
            a[x] += y;
            x += x & -x;
        }
    }
    int query(int x)
    {
        int res{};
        while(x)
        {
            res += a[x];
            x -= x&-x;
        }
        return res;
    }
};
void solve()
{
    int n, m,mx{};cin >> n >> m;
    vector<int>a(n);
    for(int i = 0 ;i < n ;i ++ ) 
    {
        cin >> a[i];
        a[i] ++;
        mx = max(mx, a[i]);
    }
    BIT bit(mx + 1);
    for(int i = 1 ;i <= mx + 1 ;i ++ ) bit.add(i, 1);
    vector<int>cnt(mx + 1, 0);
    for(int i = 0 ;i < m ; i ++ )
    {
        if(!cnt[a[i]]) bit.add(a[i], -1);
        cnt[a[i]] ++;
    }
    // for(int i = 1; i <= n;i ++ ) cout << "TEST : " << cnt[i] << '\n'; 
    auto find = [&]()->int
    {
        int l = 1, r = mx + 1;
        while(l < r)
        {
            int mid = l + r >> 1;
            if(bit.query(mid) >= 1) r = mid;
            else l = mid + 1;
        }
        // cout << "TEST : " << l << " " << bit.query(l) << '\n';
        return l;
    };
    int res = find();
    // cout << "TEST : " << find() << '\n';
    for(int i = m ;i < n; i ++ )
    {
        cnt[a[i - m]] --;
        if(!cnt[a[i - m]]) bit.add(a[i - m], 1);
        if(!cnt[a[i]]) bit.add(a[i], -1);
        cnt[a[i]] ++;
        res = min(res, find());
    }
    cout << res - 1 << '\n';
}   

int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

人鱼公主·二重唱

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
constexpr ll INF = 1e18,P = 998244353;
struct Z
{
    ll x;
    Z(ll v = 0){
        x = (v % P + P) % P;
    }
    Z& operator += (const Z & other){
        x += other.x;
        if(x >= P) x -= P;
        return *this;
    }  
    Z& operator -= (const Z & other){
        x -= other.x;
        if(x < 0) x += P;
        return *this;
    }  
    Z& operator *= (const Z & other){
        x = (ll)x * other.x % P;
        return *this;
    } 
    Z& operator /= (const Z & other){
        return (*this) *= other.inv();
    }
    friend Z operator + (Z a, const Z& b){
        return a += b;
    }
    friend Z operator - (Z a, const Z& b){
        return a -= b;
    }
    friend Z operator * (Z a, const Z& b){
        return a *= b;
    }
    friend Z operator / (Z a, const Z& b){
        return a /= b;
    }
    //比较
    friend bool operator == (const Z& a, const Z& b){
        return a.x == b.x;
    }
    friend bool operator != (const Z& a, const Z& b){
        return a.x != b.x;
    }
    
    //输入输出
    friend ostream& operator << (ostream& os, const Z& m){
        return os << m.x;
    }
    friend istream& operator >> (istream& is, Z& m){
        ll v;is >> v;
        m = Z(v);
        return is;
    }
    
    Z qmi(ll k) const
    {
        Z res(1), a(x);
        while(k)
        {
            if(k & 1) res *= a;
            a *= a;
            k >>= 1;
        }
        return res;
    }
    Z inv() const {
        return qmi(P - 2);
    }
};
array<Z, 3>Empty;
struct Node
{
    Z sum1, sum2, sum3;
    Z sum, change = INF;
}Seg[100000 << 2];
int n, m;
void push_up(int p)
{
    Seg[p].sum1 = Seg[p << 1].sum1 + Seg[p << 1 | 1].sum1;
    Seg[p].sum2 = Seg[p << 1].sum2 + Seg[p << 1 | 1].sum2;
    Seg[p].sum3 = Seg[p << 1].sum3 + Seg[p << 1 | 1].sum3;
}
void build(vector<Z>&a, int p = 1, int s = 1, int t = n)
{
    if(s == t)
    {
        Seg[p].sum1 = a[s];
        Seg[p].sum2 = a[s] * a[s];
        Seg[p].sum3 = a[s] * a[s] * a[s];
        return;
    }
    int mid =  s + t >> 1;
    build(a, p << 1, s, mid);
    build(a, p << 1 | 1, mid + 1, t);
    push_up(p);
}
void apply_s(Z c, int p = 1, int s = 1, int t = n)
{
    Seg[p].sum += c;
    Seg[p].sum3 += 3 * c * c * Seg[p].sum1 + 3 * c  * Seg[p].sum2 + c * c * c * (t - s + 1); 
    Seg[p].sum2 += 2 * c * Seg[p].sum1 + c * c * (t - s + 1);
    Seg[p].sum1 += c * (t - s + 1);
}
void apply_c(Z c, int p = 1, int s = 1, int t = n)
{
    Seg[p].sum = 0;
    Seg[p].change = c;
    Seg[p].sum3 = c * c * c * (t - s + 1);
    Seg[p].sum2 = c * c * (t - s + 1);
    Seg[p].sum1 = c * (t - s + 1);
}
void push_down(int p, int s ,int t)
{
    int mid = s + t >> 1;
    if(Seg[p].change != INF)
    {
        apply_c(Seg[p].change, p << 1, s, mid);
        apply_c(Seg[p].change, p << 1 | 1, mid + 1, t);
        Seg[p].change = INF;
    }
    if(Seg[p].sum != 0)
    {
        apply_s(Seg[p].sum, p << 1, s, mid);
        apply_s(Seg[p].sum, p << 1 | 1, mid + 1, t);
        Seg[p].sum = 0;
    }
}
void add(int l, int r, Z c , int p = 1, int s = 1, int t = n)
{
    if(l <= s && t <= r)
    {
        apply_s(c, p, s, t);
        return;
    }
    int mid = s +t >> 1;
    push_down(p, s, t);
    if(mid >= l) add(l , r, c, p << 1 , s , mid);
    if(mid + 1 <= r) add(l , r, c , p << 1 | 1, mid + 1, t);
    push_up(p);
}
void update(int l, int r, Z c , int p = 1, int s = 1, int t = n)
{
    if(l <= s && t <= r)
    {
        apply_c(c, p, s, t);
        return;
    }
    int mid = s +t >> 1;
    push_down(p, s, t);
    if(mid >= l) update(l , r, c, p << 1 , s , mid);
    if(mid + 1 <= r) update(l , r, c , p << 1 | 1, mid + 1, t);
    push_up(p);
}
array<Z, 3>query(int l, int r ,int p = 1, int s = 1, int t = n)
{
    if(l <= s && t <= r) return {Seg[p].sum1, Seg[p].sum2, Seg[p].sum3};
    int mid = s + t >> 1;
    push_down(p, s, t);
    array<Z, 3>cres1 = Empty, cres2 = Empty;
    if(mid >= l) cres1 = query(l , r, p << 1, s, mid);
    if(mid + 1 <= r) cres2 = query(l, r, p << 1 | 1, mid + 1, t);
    if(cres1 == Empty) return cres2;
    if(cres2 == Empty) return cres1;
    array<Z, 3>res;
    for(int i = 0 ;i < 3; i ++ ) res[i] = cres1[i] + cres2[i];
    return res;
}
void _init_(){
    for(int i = 0 ;i < 3; i ++ ) Empty[i] = INF;
}
void solve()
{
    cin >> n >> m;
    vector<Z>a(n + 1);
    for(int i = 1; i <= n ;i ++ ) cin >> a[i];
    build(a);
    while(m -- )
    {
        int op, l, r, k;cin >> op;
        if(op == 1)
        {
            cin >> l >> r >> k;
            add(l, r, k);
        }
        else if(op == 2)
        {
            cin >> l >> r >> k;
            update(l, r, k);
        }
        else if(op == 3)
        {
            cin >> l >> r;
            array<Z, 3> t = query(l, r);
            Z ave = t[0] / (r - l + 1);
            Z res = t[1] - 2 * ave * t[0] + ave * ave * (r - l + 1);
            cout << res / (r - l + 1) << '\n';
        }
        else if(op == 4)
        {
            cin >> l >> r;
            array<Z, 3> t = query(l, r);
            Z ave = t[0] / (r - l + 1);
            //a3 - 3ave * a * a + 3 ave * ave * a - ave * ave * ave
            Z res = t[2] - 3 * ave * t[1] + 3 * ave * ave * t[0] - ave * ave * ave * (r - l + 1);
            cout << res / (r - l + 1)<< '\n';
        }
    }
}

int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    _init_();
    int _ = 1;
    while( _ -- ) solve();
}

8.29

E - Train

看来dij确实是只要求正权边就可以用呢

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll ,ll>;
constexpr ll INF = 1e15,P = 998244353;
// struct Z
// {
//     ll x;
//     Z(ll v = 0){
//         x = (v % P + P) % P;
//     }
//     Z& operator += (const Z & other){
//         x += other.x;
//         if(x >= P) x -= P;
//         return *this;
//     }  
//     Z& operator -= (const Z & other){
//         x -= other.x;
//         if(x < 0) x += P;
//         return *this;
//     }  
//     Z& operator *= (const Z & other){
//         x = (ll)x * other.x % P;
//         return *this;
//     } 
//     Z& operator /= (const Z & other){
//         return (*this) *= other.inv();
//     }
//     friend Z operator + (Z a, const Z& b){
//         return a += b;
//     }
//     friend Z operator - (Z a, const Z& b){
//         return a -= b;
//     }
//     friend Z operator * (Z a, const Z& b){
//         return a *= b;
//     }
//     friend Z operator / (Z a, const Z& b){
//         return a /= b;
//     }
//     //比较
//     friend bool operator == (const Z& a, const Z& b){
//         return a.x == b.x;
//     }
//     friend bool operator != (const Z& a, const Z& b){
//         return a.x != b.x;
//     }
    
//     //输入输出
//     friend ostream& operator << (ostream& os, const Z& m){
//         return os << m.x;
//     }
//     friend istream& operator >> (istream& is, Z& m){
//         ll v;is >> v;
//         m = Z(v);
//         return is;
//     }
    
//     Z qmi(ll k) const
//     {
//         Z res(1), a(x);
//         while(k)
//         {
//             if(k & 1) res *= a;
//             a *= a;
//             k >>= 1;
//         }
//         return res;
//     }
//     Z inv() const {
//         return qmi(P - 2);
//     }
// };
// array<Z, 3>Empty;
// struct Node
// {
//     Z sum1, sum2, sum3;
//     Z sum, change = INF;
// }Seg[100000 << 2];
// void push_up(int p)
// {
//     Seg[p].sum1 = Seg[p << 1].sum1 + Seg[p << 1 | 1].sum1;
//     Seg[p].sum2 = Seg[p << 1].sum2 + Seg[p << 1 | 1].sum2;
//     Seg[p].sum3 = Seg[p << 1].sum3 + Seg[p << 1 | 1].sum3;
// }
// void build(vector<Z>&a, int p = 1, int s = 1, int t = n)
// {
//     if(s == t)
//     {
//         Seg[p].sum1 = a[s];
//         Seg[p].sum2 = a[s] * a[s];
//         Seg[p].sum3 = a[s] * a[s] * a[s];
//         return;
//     }
//     int mid =  s + t >> 1;
//     build(a, p << 1, s, mid);
//     build(a, p << 1 | 1, mid + 1, t);
//     push_up(p);
// }
// void apply_s(Z c, int p = 1, int s = 1, int t = n)
// {
//     Seg[p].sum += c;
//     Seg[p].sum3 += 3 * c * c * Seg[p].sum1 + 3 * c  * Seg[p].sum2 + c * c * c * (t - s + 1); 
//     Seg[p].sum2 += 2 * c * Seg[p].sum1 + c * c * (t - s + 1);
//     Seg[p].sum1 += c * (t - s + 1);
// }
// void apply_c(Z c, int p = 1, int s = 1, int t = n)
// {
//     Seg[p].sum = 0;
//     Seg[p].change = c;
//     Seg[p].sum3 = c * c * c * (t - s + 1);
//     Seg[p].sum2 = c * c * (t - s + 1);
//     Seg[p].sum1 = c * (t - s + 1);
// }
// void push_down(int p, int s ,int t)
// {
//     int mid = s + t >> 1;
//     if(Seg[p].change != INF)
//     {
//         apply_c(Seg[p].change, p << 1, s, mid);
//         apply_c(Seg[p].change, p << 1 | 1, mid + 1, t);
//         Seg[p].change = INF;
//     }
//     if(Seg[p].sum != 0)
//     {
//         apply_s(Seg[p].sum, p << 1, s, mid);
//         apply_s(Seg[p].sum, p << 1 | 1, mid + 1, t);
//         Seg[p].sum = 0;
//     }
// }
// void add(int l, int r, Z c , int p = 1, int s = 1, int t = n)
// {
//     if(l <= s && t <= r)
//     {
//         apply_s(c, p, s, t);
//         return;
//     }
//     int mid = s +t >> 1;
//     push_down(p, s, t);
//     if(mid >= l) add(l , r, c, p << 1 , s , mid);
//     if(mid + 1 <= r) add(l , r, c , p << 1 | 1, mid + 1, t);
//     push_up(p);
// }
// void update(int l, int r, Z c , int p = 1, int s = 1, int t = n)
// {
//     if(l <= s && t <= r)
//     {
//         apply_c(c, p, s, t);
//         return;
//     }
//     int mid = s +t >> 1;
//     push_down(p, s, t);
//     if(mid >= l) update(l , r, c, p << 1 , s , mid);
//     if(mid + 1 <= r) update(l , r, c , p << 1 | 1, mid + 1, t);
//     push_up(p);
// }
// array<Z, 3>query(int l, int r ,int p = 1, int s = 1, int t = n)
// {
//     if(l <= s && t <= r) return {Seg[p].sum1, Seg[p].sum2, Seg[p].sum3};
//     int mid = s + t >> 1;
//     push_down(p, s, t);
//     array<Z, 3>cres1 = Empty, cres2 = Empty;
//     if(mid >= l) cres1 = query(l , r, p << 1, s, mid);
//     if(mid + 1 <= r) cres2 = query(l, r, p << 1 | 1, mid + 1, t);
//     if(cres1 == Empty) return cres2;
//     if(cres2 == Empty) return cres1;
//     array<Z, 3>res;
//     for(int i = 0 ;i < 3; i ++ ) res[i] = cres1[i] + cres2[i];
//     return res;
// }
struct E
{
    int ne{}, v{},id{};
}e[100000 << 1];
int idx;
vector<int>h;
int n, m, S, G;
void _init_(){
    idx = 0;
    h.assign(n + 1, -1);
}
void add(int u ,int v, int id){e[idx].v = v, e[idx].ne = h[u],e[idx].id = id, h[u] = idx ++;}
void solve()
{
    cin >> n >> m >> S >> G;
    _init_();
    vector<vector<int>>g(n + 1);
    vector<int>T(m + 1),K(m + 1);
    for(int i = 1 ;i <= m ;i ++ )
    {
        int u, v,t, k;cin >> u >> v >> t >> k;
        add(u, v, i);
        add(v, u, i);
        T[i] = t;
        K[i] = k;
    }
    vector<ll>dis(n + 1, INF);
    vector<bool>vis(n + 1, false);
    dis[S] = 0;
    priority_queue<pll, vector<pll>, greater<pll>>q;
    q.emplace(0, S);
    while(!q.empty())
    {
        pll u = q.top();q.pop();
        if(vis[u.second]) continue;
        vis[u.second] = true;
        for(int i = h[u.second]; ~i; i = e[i].ne)
        {
            ll v = e[i].v;
            ll id = e[i].id;
            ll w = T[id];
            ll nex = ((u.first + K[id] - 1) / K[id]) * K[id];
            if(nex + w < dis[v])
            {
                dis[v] = nex + w;
                q.emplace(dis[v], v);
            }
        }
    }
    if(dis[G] == INF) cout << -1 << '\n';
    else cout << dis[G] << '\n';
}
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

D - Poker

每一个杨本点出现次数不一样忘记考虑了QAQ

#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#include <iomanip>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using pii = pair<int ,int>;
using ld = long double;
#define QWQ return 0;
constexpr ll INF = 1e18;
// ld PI = acos(-1);
// struct DSU
// {
//     vector<int>a,sz;
//     DSU(int x) 
//     {
//         a.assign(x + 10, 0);
//         sz.assign(x + 10 , 1);
//         iota(a.begin(), a.end(), 0);
//     }
//     int find(int x)
//     {
//         while(a[x] != a[a[x]]) a[x] = a[a[x]];
//         return a[x];
//     }
//     int size(int x){return sz[find(x)];}
//     void merge(int x, int y)
//     {
//         x = find(x),y = find(y);
//         if(sz[x] > sz[y]) swap(x, y);
//         sz[y] += sz[x];
//         a[x] = y;
//     }
// };
// struct E
// {
//     int ne, v;
// }e[200001 << 1];
// int idx{};
// vector<int>h;
// void add(int u, int v) {e[idx].v = v,e[idx].ne = h[u], h[u] = idx ++;}
// struct BIT
// {
//     vector<int>a;int n;
//     BIT(int x) : n(x + 1), a(x + 10, 0){}
//     void add(int x,int y)
//     {
//         while(x <= n)
//         {
//             a[x] += y;
//             x += x & -x;
//         }
//     }
//     int query(int x)
//     {
//         int res{};
//         while(x)
//         {
//             res += a[x];
//             x -= x&-x;
//         }
//         return res;
//     }
// };
//shuffled
ll pow10[33];
void _init_()
{
    pow10[0] = 1;
    for(int i = 1; i <= 32 ;i ++ ) pow10[i] = pow10[i - 1] * 10;
}
void solve()
{
    ll k;cin >> k;
    string s1, s2;cin >> s1 >> s2;
    ll a{}, b{};
    vector<ll>c0(10, 0), c1(10, 0),c2(10, 0);
    for(int i = 1 ;i < 10 ;i ++ ) c2[i] = k;
    for(int i = 0; i < 4; i ++ )
    {
        c0[s1[i] - '0'] ++;
        c1[s2[i] - '0'] ++;
        c2[s1[i] - '0'] --;
        c2[s2[i] - '0'] --;
    }
    for(int i = 1 ;i < 10 ;i ++ )
    {
        a += i * pow10[c0[i]];
        b += i * pow10[c1[i]];
    }
    ll cnt{}, all{};
    //i * 10 ^ k
    //i * 10 ^ k * 9
    // cout << "TEST : " <<a << " " << b << '\n';
    for(int i = 1; i < 10 ;i ++ )
    {
        if(!c2[i]) continue;
        c2[i] --;
        for(int j = 1 ; j < 10 ;j ++ )
        {
            if(!c2[j]) continue;
            ll nea = a + i * pow10[c0[i]] * 9;
            ll neb = b + j * pow10[c1[j]] * 9;
            
            if(i != j )
            {
                all += (c2[i] + 1) * c2[j];
                cnt += (ll)(nea > neb) * (c2[i] + 1) * c2[j];
            }
            else 
            {
                all += (c2[i] + 1) *c2[j];
                cnt += (ll)(nea > neb) * (c2[i] + 1) * c2[j];
            }
            // cout << "TEST : " << i << " " << j << '\n';
        }
        c2[i] ++;
    }
    double res = (double)cnt / (double)(all);
    cout <<fixed << setprecision(12) <<  res << '\n';
}   

int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    _init_();
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

[ABC-473]又区了QAQ只写了abc,之后补题

8.30

集训ing

8.31

[C - Digital Graffiti]

emmmm木有在25min内开出来QAQ
模拟右手摸墙走

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int ,int>;

vector<string>g;
int res{};
pii S{};
bool Fir = false;
void dfs(int x, int y, int dir = 0)// R -> U -> L ->D;
{
    if(x == S.first && y == S.second && Fir) return;
    Fir = true;
    int nx[] = {x, x - 1, x, x + 1};
    int ny[] = {y + 1, y, y - 1, y};
    if(g[nx[(dir - 1 + 4) % 4]][ny[(dir - 1 + 4) % 4]] == '.') 
    {
        res ++;
        dfs(nx[(dir - 1 + 4) % 4], ny[(dir - 1 + 4) % 4], (dir - 1 + 4) % 4);
    }
    else
    {
        while(g[nx[dir]][ny[dir]] == '#') 
        {
            (dir += 1) %= 4;
            res ++;
        }
        dfs(nx[dir], ny[dir], dir);
    }
}
void solve()
{
    int n, m;cin >> n >> m;
    g.resize(n);
    bool fl = false;
    for(int i = 0 ;i < n ;i ++ )
    {
        cin >> g[i];
        for(int j = 0 ;j < m ;j ++ )
        {
            if(g[i][j] == '#' && !fl) 
            {
                S = make_pair(i - 1, j); 
                fl = true;
            }
        }
    }
    dfs(S.first, S.second);
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while(_ -- ) solve();
}

或者由于这里的多边形不会出现自交的情况也可以用四个格子的讨论解决

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int ,int>;

vector<string>g;
void solve()
{
    int n, m;cin >> n >> m;
    g.resize(n);
    bool fl = false;
    for(int i = 0 ;i < n ;i ++ ) cin >> g[i];
    int res{};
    for(int i = 0 ;i < n - 1;i ++ )
    {
        for(int j = 0 ;j < m - 1; j ++ )
        {
            int cnt{};
            cnt += g[i][j] == '#';
            cnt += g[i + 1][j] == '#';
            cnt += g[i][j + 1] == '#';
            cnt += g[i + 1][j + 1] == '#';
            if(!cnt || cnt == 4) continue;
            if(cnt == 1) res ++;
            if(cnt == 3) res ++;
        }
    }
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while(_ -- ) solve();
}

9.1

集训 + 讲题

9.2

D - Snuke Prime

时间点拆分,挺有意思的思路
把差分的区间添加转化成了两点的两个事件然后去维护两种变量

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int ,int>;
using pll = pair<ll ,ll>;
#define QWQ return 0;

void solve()
{
    ll N, C;cin >> N >> C;
    vector<pll>T;
    for(int i = 0 ;i < N; i ++ )
    {
        ll l, r, c;cin >> l >> r >> c;
        T.emplace_back(l, c);
        T.emplace_back(r + 1, -c);
    }
    sort(T.begin(), T.end());
    ll res{}, fee{}, t{};
    for(int i = 0 ;i < T.size() ;i ++ )
    {
        res += min(C, fee) * (T[i].first - t);
        t = T[i].first;
        fee += T[i].second;
    }
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while(_ -- ) solve();
    QWQ
}

E - Peddler

这里给了\(x_i > y_i\)就已经保证的图无环了(刚刚看到的时候没反应过来QAQ)
明确了树形dp的思路剩下的就比较好解决了QWQ

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int ,int>;
using pll = pair<ll ,ll>;
#define QWQ return 0;
const ll INF = 1e18;
vector<ll>mx,A,emx;
vector<vector<int>>g;
vector<bool>vis;
void dfs(int u)
{
    mx[u] = A[u];
    for(int v : g[u])
    {
        if(vis[v])
        {
            mx[u] = max(mx[u], mx[v]);
            emx[u] = max(emx[u], mx[v]);
            continue;
        }
        vis[v] = true;
        dfs(v);
        mx[u] = max(mx[u], mx[v]);
        emx[u] = max(emx[u], mx[v]);
    }
}
void solve()
{
    int n, m;cin >> n >> m;
    A.resize(n + 1);
    g.resize(n + 1);
    vis.assign(n + 1, false);
    for(int i = 1;  i<= n ;i ++ ) cin >> A[i];
    mx.resize(n + 1);
    emx.assign(n + 1, -INF);
    for(int i = 0 ;i < m ;i ++ )
    {
        int u, v;cin >> u >> v;
        g[u].emplace_back(v);
    }
    for(int i = 1; i <= n ;i ++ )
    {
        if(vis[i]) continue;
        vis[i] = true;
        dfs(i);
    }
    ll res = -INF;
    for(int i = 1; i <=n ;i ++ )
    {
        if(emx[i] == -INF) continue; 
        res = max(res, emx[i] - A[i]);
    }
    cout << res << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while(_ -- ) solve();
    QWQ
}

F - Range Xor Query

基础线段树

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
const int N = 3e5 + 10;
ll Seg[N << 2];
int n, q;
void push_up(int p)
{
    Seg[p] = Seg[p << 1] ^ Seg[p << 1 | 1];
}
void build(vector<ll>&a, int p = 1, int s = 1, int t = n)
{
    if(s == t)
    {
        Seg[p] = a[s];
        return;
    }
    int mid = s + t >> 1;
    build(a, p << 1, s, mid);
    build(a, p << 1 | 1, mid + 1, t);
    push_up(p);
}
void update(int x, ll c, int p = 1, int s = 1, int t = n)
{
    if(s == t)
    {
        Seg[p] = c;
        return;
    }
    int mid = s + t >> 1;
    if(mid >= x) update(x, c, p << 1, s ,mid);
    else update(x, c ,p << 1 | 1, mid + 1, t);
    push_up(p);
}
ll query(int l, int r, int p = 1, int s = 1 , int t = n)
{
    if(l <= s && t <= r) return Seg[p];
    int mid = s + t >> 1;
    ll L{}, R{};
    if(mid >= l) L = query(l, r, p << 1, s, mid);
    if(mid + 1 <= r) R = query(l, r, p << 1 | 1, mid + 1, t);
    return L ^ R;
}
void solve()
{
    cin >> n >> q;
    vector<ll>A(n + 1);
    for(int i = 1; i <= n ;i ++ ) cin >> A[i];
    build(A);
    while(q -- )
    {
        int op;cin >> op;
        if(op == 1)
        {
            int x, y;cin >> x >> y;
            A[x] ^= y;
            update(x, A[x]);
        }
        else if(op == 2)
        {
            int l, r;cin >> l >> r;
            cout << query(l, r) << '\n';
        }
    }
}
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    return 0;
}

E - Akari

二分去找然后差分构建,本身没什么难度,但是比较考验码力(25min内写完比较难)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll ,ll>;
using pii = pair<int ,int>;
void debug()
{

}
void solve()
{
    int H, W, N ,M;cin >> H >> W >> N >> M;
    vector<vector<int>>pre(H + 2, vector<int>(W + 2));
    vector<pii>bull(N), block(M);
    for(int i = 0 ;i < N ; i ++ ) cin >> bull[i].first >> bull[i].second;
    for(int i = 0 ;i < M ; i ++ ) cin >> block[i].first >> block[i].second;
    vector<vector<int>>row(H + 1),col(W + 1);
    for(int i = 1 ;i <= H ;i ++ )
    {
        row[i].emplace_back(W + 1);
        row[i].emplace_back(0);
    }
    for(int i = 1 ;i <= W ;i ++ )
    {
        col[i].emplace_back(H + 1);
        col[i].emplace_back(0);
    }
    for(int i = 0 ;i < M ;i ++ )
    {
        row[block[i].first].emplace_back(block[i].second);//
        col[block[i].second].emplace_back(block[i].first);//
    }
    for(int i = 1 ;i <= H ;i ++ ) sort(row[i].begin(), row[i].end());
    for(int i = 1 ;i <= W ;i ++ ) sort(col[i].begin(), col[i].end());


    // for(int i = 1 ;i <= H ;i ++ )
    // {
    //     cout << "TEST : " << i << '\n';
    //     for(int j = 0 ;j < row[i].size() ;j ++ ) cout << row[i][j] << " \n"[j == row[i].size() - 1];
    // }


    auto insert = [&](int x1,int y1, int x2, int y2, int c)->void{
        pre[x1][y1] += c;
        pre[x2 + 1][y1] -= c;
        pre[x1][y2 + 1] -= c;
        pre[x2 + 1][y2 + 1] += c;
    };
    auto change = [&](pii x, int dir)->void
    {
        int l{}, r{};
        // cout << "TEST1 : " << x.first << " " << x.second << " " << dir << '\n';
        if(dir == 0)//上
        {
            auto&A = col[x.second];
            l = 0, r = A.size() - 1;
            while(l < r)
            {
                int mid = l + r + 1 >> 1;
                if(A[mid] <= x.first) l = mid;
                else r = mid - 1;
            }
            // cout << "TEST : " << x.first << " " << x.second << '\n';
            // cout << "TEST : " << l << " " << x.second << '\n';
            insert(A[l] + 1, x.second, x.first, x.second, 1);
        }
        if(dir == 1)//下
        {
            auto&A = col[x.second];
            l = 0, r = A.size() - 1;
            while(l < r)
            {
                int mid = l + r >> 1;
                if(A[mid] >= x.first) r = mid;
                else l = mid + 1;
            }
            insert(x.first, x.second, A[l] - 1, x.second, 1);
        }
        if(dir == 2)//左
        {
            auto&A = row[x.first];
            l = 0, r = A.size() - 1;
            while(l < r)
            {
                int mid = l + r + 1 >> 1;
                if(A[mid] <= x.second) l = mid;
                else r = mid - 1;
            }
            // cout << "TEST : " << x.first << " " << x.second << '\n';
            // cout << "TEST : " << A[l] << " " << x.second << '\n';
            // for(int i = 0 ;i < A.size() ;i ++ ) cout << A[i] << " \n"[i == A.size() - 1];
            insert(x.first, A[l] + 1, x.first, x.second, 1);
        }
        if(dir == 3)//右
        {
            auto&A = row[x.first];
            l = 0, r = A.size() - 1;
            while(l < r)
            {
                int mid = l + r>> 1;
                if(A[mid] >= x.second) r = mid;
                else l = mid + 1;
            }
            insert(x.first, x.second, x.first, A[l] - 1, 1);
        }
    };
    for(int i = 0 ;i < N ;i ++ ) for(int j = 0 ;j < 4; j ++ ) change(bull[i], j);
    for(int i = 1; i <= H ;i ++ ) for(int j = 1 ; j <= W; j ++ )
    {
        pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + pre[i][j];
    }
    int res{};
    // for(int i = 1 ;i <= H; i ++ ) for(int j  = 1; j <= W; j ++ ) cout << pre[i][j] << " \n"[j == W];
    for(int i = 1 ;i <= H; i ++ ) for(int j  = 1; j <= W; j ++ ) res += pre[i][j] != 0;
    cout << res << '\n';
}
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    return 0;
}

9.3

集训 + 现在团队赛vp中

9.4

身体不适调养中

9.5

集训 + 学习差分约束ing

9.6

严肃肘击ICPC网络赛中
vp了一下ABC(好像难度比之前低了些许?)

A - Not X

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
using ll = long long;
using pii = pair<int , int>;
using pll = pair<ll ,ll>;
const ll N = 50005, M = 50005;
#define QWQ return 0;

void solve()
{
    ll x;cin >> x;
    x --;
    cout << (x + 1) % 3 + 1 << '\n';
}
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

B - Exit Order

刚打完网络赛回来有点晕晕的QAQ,没注意到下标问题

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int , int>;
using pll = pair<ll ,ll>;
const ll N = 50005, M = 50005;
#define QWQ return 0;

void solve()
{
    ll n;cin >> n;
    vector<ll>P(n + 1);
    for(int i = 1; i <= n ;i ++ ) cin >> P[i];
    for(int i = 1,cnt = 1; i <= n;i += 10, cnt ++)
    {
        for(int j = 0 ;j < 10  && j + i <= n;j ++ )
        {
            if(P[i + j] > 10 * cnt)
            {
                cout << "No\n";
                return;
            }
        }
    }
    cout << "Yes\n";
}
//measure
//congestion
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

C - Remove and Append

离线的基础运用

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int , int>;
using pll = pair<ll ,ll>;
const ll N = 50005, M = 50005;
#define QWQ return 0;
int cnt[110]{};
void solve()
{
    int n, q;cin >> n >> q;
    vector<int>A(n);
    for(int i =0 ; i < n; i ++ ) cin >> A[i];
    vector<int>Q(q);
    for(int i = 0; i < q; i ++ ) cin >> Q[i];
    vector<int>vis(n + 1, 0);
    vector<int>res;
    for(int i = q - 1; i >= 0; i -- )
    {
        if(vis[Q[i]]) continue;
        vis[Q[i]] = true;
        res.emplace_back(Q[i]);
    }
    for(int i = n - 1; i >= 0 ;i -- )
    {
        if(vis[A[i]]) continue;
        res.emplace_back(A[i]);
    }
    for(int i = res.size() - 1; i >= 0 ;i -- ) cout<< res[i] << " \n"[!i];
}
//measure
//congestion
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

D - Outweigh

一开始逗比了忘记输出YES了我说怎么一直WA。QAQ

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int , int>;
using pll = pair<ll ,ll>;
const ll N = 50005, M = 50005,INF = 1000000000000000000LL;
#define QWQ return 0;


void solve()
{
    int n;cin >> n;
    vector<ll>A(n + 1),B(n + 1);
    for(int i = 1; i <= n ;i ++ ) cin >> A[i];
    for(int i = 1; i <= n ;i ++ ) cin >> B[i];
    bool fl = false;
    int lc = -1;
    ll dif0{}, dif1{};
    for(int i = 1; i <= n ;i ++ )
    {
        if(B[i] >= A[i]) dif0 += B[i] - A[i];
        else dif1 += A[i] - B[i];
    }
    //dif0 >= INF * dif1 
    if(!dif1 || dif0 / dif1 >= INF)
    {
        cout << "No\n";
        return;
    }
    cout << "Yes\n";
    for(int i = 1;  i<= n ;i ++ )
    {
        if(B[i] >= A[i]) cout << 1 << " \n"[i == n];
        else cout << INF << " \n"[i == n];
    }
    
}
//measure
//congestion
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
}

E - One Time Coupon

这个遍历优惠券没有想到,所以vp的时候没开出来QAQ,exp++

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int , int>;
using pll = pair<ll ,ll>;
const ll N = 50005, M = 50005,INF = 1000000000000000000LL;
#define QWQ return 0;
//https://vjudge.net/contest/845501#problem/C
void solve()
{
    ll n, sum{};cin >> n;
    vector<ll>A(n + 1), B(n + 1);
    for(int i = 1; i <= n ;i ++ ) 
    {
        cin >> A[i] >> B[i];
        sum += A[i];
    }
    ll res = sum;
    ll mnA = A[1];
    //记有k种用券买,n - k原价买
    //n - k >= k
    //n / 2 >= k
    //没事
    //如果n - k < k
    //需要2k - n去填空白
    //k = n / 2 + (n & 1) ~ n
    //要额外去买
    vector<ll>dif(n + 1, 0);
    for(int i = 1; i <= n ; i ++ )
    {
        dif[i] += A[i] - B[i];
        mnA = min(mnA, A[i]);
    }
//     cout << "TESt : " << mnA << '\n';
    sort(dif.begin() + 1, dif.end(), greater<ll>());
    for(int i = 1; i <= n ; i ++ ) dif[i] += dif[i - 1];

    for(int k = 0; k <= n ; k ++ )
    {
        res = min(res,sum - dif[k] + max(0LL, 2 * k - n) * mnA);
    }
    cout << res << '\n';
}
//measure
//congestion
int main() 
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;cin >> _;
    while( _ -- ) solve();
}

9.7

D - Redistribution

基本排列组合QWQ

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int ,int>;
using pll = pair<ll ,ll>;
#define QWQ return 0;
constexpr ll P = 1000000007, INF = 1000000000000000000LL, inf = 1000000000;
ll dp[2001][2001]{};
void solve()
{
    ll n;cin >> n;
    if(n < 3)
    {
        cout << 0 << '\n';
        return;
    }
    ll res{};
    dp[0][0] = 1;
    for(int i = 0; i <= 2000; i ++ ) for(int j = 0 ;j <= 2000; j ++ )
    {
        if(i - 1 >= 0) (dp[i][j] += dp[i - 1][j]) %= P;
        if(j - 1 >= 0) (dp[i][j] += dp[i][j - 1]) %= P;
    }
    for(int i = n / 3; i >= 1; i -- )
    {
        ll a = i, b = n - 3 * i;
        (res += dp[a - 1][b]) %= P;
    }
    cout << res << '\n'; 
}
int main()
{
	cin.tie(0)->ios::sync_with_stdio(false);
	int _ = 1;
	while( _ -- ) solve();
	QWQ
}

E - Transformable Teacher

成功在25min内开出来力QWQ

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int ,int>;
using pll = pair<ll ,ll>;
#define QWQ return 0;
constexpr ll P = 1000000007, INF = 1000000000000000000LL, inf = 1000000000;
void solve()
{
    int n ,m ;cin >> n >> m;
    vector<ll>H(n + 1);
    set<ll>s;
    for(int i = 1 ; i <= n ; i ++ ) cin >> H[i];
    for(int i = 1 ; i <= m ; i ++ ) 
    {
        ll x;cin >> x;
        s.insert(x);
    }
    sort(H.begin() + 1, H.end());
    vector<ll>pre(n + 2), suf(n + 2);
    for(int i = 1 ;i <= n; i ++ )
    {
        if(i & 1) continue;
        pre[i] = abs(H[i] - H[i - 1]);
    }
    for(int i = 1; i <= n ;i ++ ) pre[i] += pre[i - 1];
    for(int i = n ;i >= 1; i -- )
    {
        if(i & 1) continue;
        suf[i] = abs(H[i] - H[i + 1]);
    }
    for(int i = n ;i >= 1 ; i-- ) suf[i] += suf[i + 1];
    //计算ignore[i]忽视点i计算minabs
    vector<ll>ignore(n + 1);
    for(int i = 1 ; i<= n ;i ++ )
    {
        if(i & 1) ignore[i] = pre[i - 1] + suf[i + 1];
        else
        {
            if(i - 2 >= 0 )ignore[i] += pre[i - 2];
            if(i + 2 <= n )ignore[i] += suf[i + 2];
            if(i - 1 >= 0 && i + 1 <= n) ignore[i] += abs(H[i - 1] - H[i + 1]);
        }
    }
    //1 2 3 4 5 6 7 8 9
    // cout << "TST : " << suf[2] << '\n';
    // for(int i = 1 ;i <= n ;i ++ ) cout << ignore[i] << " \n"[i == n];

    ll res = INF;
    for(int i = 1; i <= n ;i ++ )
    {
        auto it = s.lower_bound(H[i]);
        // cout << "TEST : " << *it << "\n";
        if(it != s.end()) res = min(res, abs((*it) - H[i]) + ignore[i]);
        if(it != s.begin())
        {
            -- it;
            res = min(res, abs((*it) - H[i]) + ignore[i]);
        }
    }
    cout << res << '\n';
}
int main()
{
	cin.tie(0)->ios::sync_with_stdio(false);
	int _ = 1;
	while( _ -- ) solve();
	QWQ
}

9.8

网络赛补题ing

L. Longest Common Prefix

用trie树处理前缀挺明显的,但是感觉这里的思路转化很绕
核心:把最大前缀明确转化为trie树深度
转化为\(M[d]\)即为当前深度经过的串的最多数量
然后\(F[m]\)就可以转化为满足条件(即为\(M[d] >= m\))的\(M[d]\)的数量进行处理
然后重点观察到对于串插入的时候\(M[d]\)最多会 + 1然后当前深度原本\(F[M[d] + 1]\)是不满足的现在满足了,可以加一

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define QWQ return 0;
const ll MaxN = 500000 + 10; 

struct Node
{
    int ne[26]{};
}trie[MaxN];
int idx,M[MaxN]{},dpth[MaxN]{},cnt[MaxN]{},F[MaxN]{};
ll res{};
void add(string&s, int i)
{
    //计算从字典树中取j个的最大前缀
    //可以处理M[d]在深度d下最多可以找到多少共前缀的串
    //那么有F[m]可以定义为有多少的d满足M[d] >= m

    //首先注意到这里M[d]的增长是随着串的插入连续增长的(一直+1)
    //并且如果M[d] + 1了,那么原本的邻界点j = M[d] + 1就恰好被我们满足了,所以此时F[j = M[d] + 1]就 + 1
    //最终即为记m = M[d] + 1
    //为答案res += -((F[m] - 1) ^ m) + (F[m] ^ m)即可
    //但是注意一点这样差分更新的要求res里卖弄原本有(F[m] - 1) ^ m而这里i还没加进去,所以要要求m < i
    //F[i]我们只需要最后加上即可
    int p{}, d{};
    for(char& c : s)
    {
        if(!trie[p].ne[c - 'a']) trie[p].ne[c - 'a'] = ++ idx;
        p = trie[p].ne[c - 'a'];
        cnt[p] ++;
        d ++;
        if(cnt[p] > M[d])
        {
            int m = cnt[p];
            M[d] = m;
            F[m] ++;
            if(m < i) res += -((F[m] - 1) ^ m) + (F[m] ^ m);
        }
    }
    res += F[i] ^ i;
}
void solve()
{
    int n;cin >> n;
    for(int i = 1 ; i<= n ;i ++ )
    {
        string s;cin >> s;
        add(s, i);
        cout << res << '\n';
    }
}
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

E - Dist Max

这个45度变化挺有意思的(计算曼哈顿距离的一种化简方式)
(原来绝对值的处理还可以用max表示,不错QWQ)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define QWQ return 0;
const ll N = 500000 + 10, INF = 1e18; 

void solve()
{
    int n;cin >> n;
    vector<ll>X(n + 1), Y(n + 1);
    //|x0 - x1| + |y0 - y1|
    // = max(Z0 - Z1, W0 - W1)
    //Zi = xi + yi
    //Wi = xi - yi
    // = max{max(Z) - min(Z) , max(W) - min(W)}
    ll mxZ = -INF, mnZ = INF;
    ll mxW = -INF, mnW = INF;
    for(int i = 1 ; i<= n ;i ++ )
    {

        cin >> X[i] >> Y[i];
        mxZ = max(mxZ, (ll)(X[i] + Y[i]));
        mnZ = min(mnZ, (ll)(X[i] + Y[i]));
        mxW = max(mxW, (ll)(X[i] - Y[i]));
        mnW = min(mnW, (ll)(X[i] - Y[i]));
    }
    cout << max(mxZ - mnZ , mxW - mnW) << '\n';
}
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

E - Alternating Costs

分类讨论构造出\(g(k)\)(即为对应步数到达所以要的代价)
注:这里回头代价可能更小

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define QWQ return 0;
const ll N = 500000 + 10, INF = 1e18; 

ll Sol(ll A, ll B, ll X, ll Y)
{
    X = abs(X), Y = abs(Y);
    if(A > B) swap(A, B);
    if(X > Y) swap(X, Y);
    //g(k) = 2kA + (Y - K)(B - A)
    ll mid = X + Y >> 1;
    return min(2LL * mid * A + (Y - mid) * (B - A), 2LL * Y * A);
}
void solve()
{
    ll A, B,X,Y;cin >> A >> B >> X >> Y;
    X = abs(X), Y = abs(Y); 
    ll res = INF;
    if((X + Y) & 1)
    {
        res = min(res, Sol(A, B, X - 1, Y) + A);
        res = min(res, Sol(A, B, X, Y - 1) + B);
        //X + 1和Y + 1 ?
        cout << res << '\n';
        return; 
    }          
    cout << Sol(A, B, X , Y) << '\n';          
}
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;cin >> _;
    while( _ -- ) solve();
    QWQ
}

复盘start!QWQ

D - Forbidden Difference

时间有点久了,还是没能在25min内开掉,不过就超了一点点时应该问题不大QWQ

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define QWQ return 0;
const ll N = 500000 + 10, INF = 1e18; 

void solve()
{
    ll n,D,mx{};cin >> n >> D;
    vector<ll>A(n + 1),cnt(2000000 + 10, 0);
    for(int i = 1 ;i <= n ;i ++ )
    {
        cin >> A[i];
        cnt[A[i]] ++;
        mx = max(A[i], mx);
    }
    sort(A.begin() + 1, A.end());
    if(!D)
    {
        ll res{};
        for(int i = 0 ; i <= mx; i ++ ) res += cnt[i] != 0;
        res = n - res;
        cout << res << '\n';
        return;
    }
    //要求不存在Bi - Bj == D
    //可以把A[i] -> x + kD
    //x在[0, D),
    //dp[i] = dp[i - 1] + cnt[x + id], dp[i - 2] + cnt[x + (i - 1)d];
    ll res{};
    for(int i = 0 ; i < D; i ++ )
    {
        vector<ll>dp((mx - i) / D + 2, INF);
        dp[0] = 0;
        dp[1] = min(cnt[i], cnt[i + D]);
        for(int j = 2; j <= (mx - i) / D; j ++ )
        {
            if(j - 1 >= 0) dp[j] = min(dp[j], dp[j - 1] + cnt[i + j * D]);
            if(j - 2 >= 0) dp[j] = min(dp[j], dp[j - 2] + cnt[i + (j - 1) * D]);
        }
        // cout << "TEST : " << dp[(n - i)/D + 1] << '\n';
        res += dp[(mx - i) / D];
    }
    cout << res << '\n';
}
int main()
{
    cin.tie(0)->ios::sync_with_stdio(false);
    int _ = 1;
    while( _ -- ) solve();
    QWQ
}

posted @ 2026-08-19 18:30  Mikan_QWQ  阅读(27)  评论(0)    收藏  举报