CSP-S 31

10.14

看大家得分跟信心赛似的,就我一个唐诗写了一场暴力 \(\ldots\)

开场t1没切出来就开始慌了,之后就想着多打暴力拿部分分,导致t2得出的性质没有推广,t3,t4暴力都没写出来(这俩得出性质/部分性质后比暴力好写多了)\(\ldots\)

t1

看到题就想二分,结果根本就分不出来 \(\ldots\)

发现我好像对于在线查询有种别样的执着,每次都不会离线和预处理 \(\ldots\)

观察到值域很小,空间可接受,于是直接一个 \(O(nV)\) 巨大预处理,之后单次询问是 \(O(\log(n)\log(V))\) ,所以总复杂度为 \(O(nV+q\log(n)\log(V))\)(其实还有单log做法)。

预处理:对于每个 \(x\) ,记录所有 \(x|a_i=x\)\(i\) ,查询时二分查找即可。

code

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
int n, q;
int a[N], b[N];
vector<int> f[1024];

inline long long solve(int l, int r, int x)
{
    long long ans = 0;
    int now = l;
    while (now <= r)
    {
        // cerr << "&\n";
        if (f[x].size() == 0 || f[x][f[x].size() - 1] < now)
            break;
        // cerr << "!\n";
        int id = *lower_bound(f[x].begin(), f[x].end(), now);
        if (id > r)
            break;
        // int nxt = f[x][id];
        ans += b[id], x -= a[id];
        now = id + 1;
        // cerr << "id=" << id << " now=" << now << "\n";
    }
    // cerr << "$ans=" << ans << "\n";
    return ans;
}

signed main()
{
#ifndef ANS
    freopen("expedition.in", "r", stdin);
    freopen("expedition.out", "w", stdout);
#else
    freopen("ex_expedition1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> a[i];
        for (int val = a[i]; val <= 1023; ++val)
        {
            if ((val | a[i]) == val)
                f[val].emplace_back(i);
        }
    }
    for (int i = 1; i <= n; ++i)
        cin >> b[i];
    cin >> q;
    int l, r, x;
    long long ans = 0;
    while (q--)
    {
        cin >> l >> r >> x;
        ans ^= solve(l, r, x);
    }
    cout << ans;
    return 0;
}

t2

树的性质是好观察的,层数之差为奇数答案为 1 ,否则答案为 2 。

其实继续思考(或观察大阳历)就能发现答案只有 \(-1,0,1,2\) 但是我当时甚至都没有多看那两个非树的大阳历一眼 \(\ldots\)

继续推广可知,当两点间距离为奇数时,答案为 1 ,否则为 2 (在同一连通块内)。

考虑加边:满3加边,若存在奇环,则块内任意两点都可通过环改变这两点路径的奇偶性(画图可知)。

因此重点为判奇环。

奇偶染色即可。

具体看代码

code

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int T, n, m, q, cnt;
vector<int> e[N];
bool flag[N], gd[N];
int col[N], belong[N];

void dfs(int x, int pre)
{
    belong[x] = cnt;
    if (col[x] && col[x] != pre)
        gd[cnt] = 1;
    else
        col[x] = pre;
    flag[x] = 1;
    for (auto y : e[x])
    {
        if (col[y] && col[y] == pre)
            gd[cnt] = 1;
        if (flag[y])
            continue;
        dfs(y, ((pre - 1) ^ 1) + 1);
    }
}

signed main()
{
    freopen("teleport.in", "r", stdin);
    freopen("teleport.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> T;
    cin >> n >> m;
    for (int i = 1, u, v; i <= m; ++i)
    {
        cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    for (int i = 1; i <= n; ++i)
    {
        if (!flag[i])
            ++cnt, dfs(i, 1);
    }
    // for (int i = 1; i <= n; ++i)
    //     cerr << col[i] << "\n";
    // cerr << gd[1] << "\n";
    cin >> q;
    int s, t;
    while (q--)
    {
        cin >> s >> t;
        if (s == t)
        {
            cout << 0 << "\n";
            continue;
        }
        if (belong[s] != belong[t])
        {
            cout << -1 << "\n";
            continue;
        }
        if (gd[belong[s]])
        {
            cout << 1 << "\n";
            continue;
        }
        if (col[s] != col[t])
            cout << 1 << "\n";
        else
            cout << 2 << "\n";
    }
    return 0;
}

t3

这题我觉得简单思考就解决了,但我当时一心暴力。

限制转化为形如 xxyzxy

之后暴力枚举 x,y,z 即可。

60pts

考虑到对于 z 只要求与 x,y 不同即可,根本不用枚举。

于是\(O(nk^2)\) ,通过。

code

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int mod = 114514;
string s;
int n, ans;

inline int sum(int x)
{
    if (x >= mod)
        return x - mod;
    return x;
}

inline void solve(char x, char y)
{
    int len1 = 0, len2 = 0, len3 = 0, len4 = 0, len5 = 0, len6 = 0;
    for (int i = 1; i <= n; ++i)
    {
        if (s[i] == x)
        {
            len5 += len4, len2 += len1, ++len1;
            len5 = sum(len5), len2 = sum(len2), len1 = sum(len1);
        }
        else if (s[i] == y)
        {
            len6 += len5, len3 += len2;
            len6 = sum(len6), len3 = sum(len3);
        }
        else
        {
            len4 += len3;
            len4 = sum(len4);
        }
    }
    ans += len6;
    ans = sum(ans);
}

signed main()
{
    freopen("anc.in", "r", stdin);
    freopen("anc.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> s;
    n = s.size();
    s = " " + s;
    for (int i = 1; i <= 26; ++i)
        for (int j = 1; j <= 26; ++j)
        {
            if (i == j)
                continue;
            solve((char)i + 'a' - 1, (char)j + 'a' - 1);
        }
    cout << (ans + mod) % mod;
    return 0;
}

posted @ 2025-10-20 21:48  HS_fu3  阅读(21)  评论(0)    收藏  举报