首页 > 其他分享 >20240130

20240130

时间:2024-01-30 22:12:18浏览次数:85  
标签:return rep int eg 20240130 sum define

A. 01矩形

枚举上下界,two-pointers

// Author: xiaruize
// #pragma GCC optimize("-ofast")
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define debug(x) cerr << #x << ": " << x << endl
#define mms(arr, n) memset(arr, n, sizeof(arr))
#define rep(i, a, n) for (int i = (a); i <= (n); ++i)
#define per(i, n, a) for (int i = (n); i >= (a); --i)
int max(int a, int b)
{
	if (a > b)
		return a;
	return b;
}
int min(int a, int b)
{
	if (a < b)
		return a;
	return b;
}
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 5e4 + 10;

// bool st;
int n, m;
char s[35][N];
int llim, rlim;
int cnt[N][35];
// bool en;

void solve()
{
	cin >> n >> m;
	rep(i, 1, n) cin >> (s[i] + 1);
	rep(i, 1, n)
	{
		rep(j, 1, m)
		{
			cnt[j][i] = cnt[j][i - 1] + (s[i][j] == '1');
		}
	}
	cin >> llim >> rlim;
	if (llim == 0 && rlim == n * m)
	{
		cout << (long long)n * (long long)(n + 1) / 2ll * (long long)m * (long long)(m + 1) / 2ll << endl;
		return;
	}
	long long res = 0;
	rep(u, 1, n)
	{
		rep(d, u, n)
		{
			int curl = 0, curr = 0, r = 0, rr = 0;
			for (int l = 1; l <= m; l++)
			{
				while (r <= m && curl < llim)
				{
					r++;
					curl += cnt[r][d] - cnt[r][u - 1];
				}
				while (rr <= m && curr <= rlim)
				{
					rr++;
					curr += cnt[rr][d] - cnt[rr][u - 1];
				}
				// cerr << u << ' ' << d << ' ' << l << ' ' << r << ' ' << rr << endl;
				res += 1ll * (rr - r);
				curl -= cnt[l][d] - cnt[l][u - 1];
				curr -= cnt[l][d] - cnt[l][u - 1];
			}
		}
	}
	cout << res << endl;
}

signed main()
{
	// freopen("a.in", "r", stdin);
	// freopen("a.out", "w", stdout);
	// cerr<<(&en-&st)/1024.0/1024.0<<endl;
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	// cin >> testcase;
	while (testcase--)
		solve();
	return 0;
}

B. 商店购物

前面 \(dp\) 后面组合

dp可以考虑前缀和优化或者容斥

// Author: xiaruize
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define debug(x) cerr << #x << ": " << x << endl
#define mms(arr, n) memset(arr, n, sizeof(arr))
#define rep(i, a, n) for (int i = (a); i <= (n); ++i)
#define per(i, n, a) for (int i = (n); i >= (a); --i)
int max(int a, int b)
{
    if (a > b)
        return a;
    return b;
}
int min(int a, int b)
{
    if (a < b)
        return a;
    return b;
}
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 2e5 + 10;

int fac[10000009], inv[10000009];
int qpow(int a, int b)
{
    int ans = 1;
    while (b)
    {
        if (b & 1)
            ans = (ans * a) % MOD;
        a = (a * a) % MOD;
        b /= 2;
    }
    return ans;
}
void init()
{
    fac[0] = 1;
    for (int i = 1; i <= 10000000; i++)
        fac[i] = (fac[i - 1] * i) % MOD;
    inv[10000000] = qpow(fac[10000000], MOD - 2);
    for (int i = 10000000 - 1; i >= 0; i--)
        inv[i] = (inv[i + 1] * (i + 1)) % MOD;
}
int C(int x, int y)
{
    if (x < 0 || x < y || y < 0)
        return 0;
    if (x == y || y == 0)
        return 1;
    else
        return fac[x] * inv[x - y] % MOD * inv[y] % MOD;
}

// bool st;
int n, m, k;
int w[305];
int dp[90005], s[90005];
// bool en;

void solve()
{
    init();
    cin >> n >> m >> k;
    rep(i, 1, m) cin >> w[i];
    int sum = 0;
    dp[0] = 1;
    rep(i, 0, min(k, 90000ll)) s[i] = 1;
    rep(i, 1, m)
    {
        sum += w[i];
        sum = min(sum, min(k, 90000ll));
        per(j, sum, 1)
        {
            if (j > w[i])
                (dp[j] += ((s[j - 1] - s[j - w[i] - 1]) % MOD + MOD) % MOD) %= MOD;
            else
                (dp[j] += s[j - 1]) %= MOD;
        }
        rep(j, 1, min(k, 90000ll))
        {
            s[j] = (s[j - 1] + dp[j]) % MOD;
            // cerr << dp[j] << ' ';
        }
        // cerr << endl;
    }
    int res = 0;
    int t = n - m;
    if (t)
        rep(i, 0, sum)
        {
            // cerr << i << ' ' << dp[i] << endl;
            res = (res + dp[i] * C(k - i + t - 1, t - 1) % MOD) % MOD;
        }
    else
        res = dp[k];
    cout << res << endl;
}

signed main()
{
    // freopen("shopping.in", "r", stdin);
    // freopen("shopping.out", "w", stdout);
    // cerr<<(&en-&st)/1024.0/1024.0<<endl;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int testcase = 1;
    // cin >> testcase;
    while (testcase--)
        solve();
    return 0;
}

C. 友好城市

今天才知道原来强联通分量除了tarjan还有别的做法

kosaraju 在 \(n\) 较小的图中可以 bitset 优化获得比 tarjan 更优的时间复杂度

然后就莫队板子了

// Author: xiaruize
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define debug(x) cerr << #x << ": " << x << endl
#define mms(arr, n) memset(arr, n, sizeof(arr))
#define rep(i, a, n) for (int i = (a); i <= (n); ++i)
#define per(i, n, a) for (int i = (n); i >= (a); --i)
int max(int a, int b)
{
    if (a > b)
        return a;
    return b;
}
int min(int a, int b)
{
    if (a < b)
        return a;
    return b;
}
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 3e5 + 10;

// bool st;
int n, m, q;
bitset<155> bt[155], bt2[155];
int tot[155][155];
pii eg[N];
bitset<155> vis;
vector<int> vec;
struct node
{
    int l, r, id;
} s[N];
// bool en;

int unit;

bool cmp(node a, node b)
{
    return (a.l / unit == b.l / unit
                ? (a.r == b.r ? 0 : ((a.l / unit) & 1) ^ (a.r < b.r))
                : a.l < b.l);
}

void dfs(int x)
{
    vis[x] = 0;
    bitset<155> tmp = (vis & bt[x]);
    int cur = tmp._Find_first();
    while (cur != 155)
    {
        dfs(cur);
        bitset<155> tmp = (vis & bt[x]);
        cur = tmp._Find_first();
    }
    // cerr << x << endl;
    vec.push_back(x);
}

int cnt = 0;

int ans[N];
void dfs2(int x)
{
    vis[x] = 0;
    cnt++;
    bitset<155> tmp = (vis & bt2[x]);
    int cur = tmp._Find_first();
    while (cur != 155)
    {
        dfs2(cur);
        bitset<155> tmp = (vis & bt2[x]);
        cur = tmp._Find_first();
    }
}

int curl = 1, curr = 0;

void add(int x)
{
    tot[eg[x].first][eg[x].second]++;
    if (tot[eg[x].first][eg[x].second] == 1)
    {
        bt[eg[x].first][eg[x].second] = 1;
        bt2[eg[x].second][eg[x].first] = 1;
    }
}

void del(int x)
{
    tot[eg[x].first][eg[x].second]--;
    if (!tot[eg[x].first][eg[x].second])
    {
        bt[eg[x].first][eg[x].second] = 0;
        bt2[eg[x].second][eg[x].first] = 0;
    }
}

void solve()
{
    cin >> n >> m >> q;
    unit = sqrt(m);
    rep(i, 1, m)
    {
        cin >> eg[i].first >> eg[i].second;
    }
    rep(i, 1, q)
    {
        cin >> s[i].l >> s[i].r;
        s[i].id = i;
    }
    sort(s + 1, s + q + 1, cmp);
    // cerr << "flag" << q << endl;
    rep(i, 1, q)
    {
        // cerr << "fl" << endl;
        int res = 0;
        auto [l, r, id] = s[i];
        vec.clear();
        // cerr << l << ' ' << r << ' ' << id << endl;
        while (curr < r)
        {
            curr++;
            add(curr);
        }
        while (curr > r)
        {
            del(curr);
            curr--;
        }
        while (curl < l)
        {
            del(curl);
            curl++;
        }
        while (curl > l)
        {
            curl--;
            add(curl);
        }
        rep(i, 1, n)
        {
            vis[i] = 1;
        }
        rep(i, 1, n)
        {
            if (vis[i])
                dfs(i);
        }
        rep(i, 1, n)
        {
            vis[i] = 1;
        }
        reverse(ALL(vec));
        for (auto v : vec)
        {
            // cerr << v << ' ';
            if (vis[v])
            {
                cnt = 0;
                dfs2(v);
                // cerr << "flag" << cnt << endl;
                res = res + cnt * (cnt - 1) / 2;
            }
        }
        // cerr << endl;
        ans[id] = res;
    }
    rep(i, 1, q) cout << ans[i] << endl;
}

signed main()
{
    freopen("friend.in", "r", stdin);
    freopen("friend.out", "w", stdout);
    // cerr<<(&en-&st)/1024.0/1024.0<<endl;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int testcase = 1;
    // cin >> testcase;
    while (testcase--)
        solve();
    return 0;
}

D. 旅行计划

6.5k的代码使我的手旋转。

树上对链做询问,还要修改,明显是树链剖分+线段树

一般来说,可以用线段树维护一个dp,但是这题中是没有决策的,也就是存在贪心

那么可以用线段树维护 \(f,g\) 分别表示在点数最小的情况下最多剩多少油,不考虑点数最多剩多少油

我们发现后一种情况的点数可以且最少为前一种情况 \(+1\),所以这是好维护的

然后考虑拿 \(20\times 20\) 的状态转移仍然不行,这时可以拿初始的状态来转移,因为初始状态下是 \(20\times 1\) 的矩阵,所以每次转移是 \(O(20)\) 的,可以通过

// Author: xiaruize
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define debug(x) cerr << #x << ": " << x << endl
#define mms(arr, n) memset(arr, n, sizeof(arr))
#define rep(i, a, n) for (int i = (a); i <= (n); ++i)
#define per(i, n, a) for (int i = (n); i >= (a); --i)
int max(int a, int b)
{
    if (a > b)
        return a;
    return b;
}
int min(int a, int b)
{
    if (a < b)
        return a;
    return b;
}
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 1e5 + 10;
const int M = 25;

// bool st;
int n;
int a[N];
vector<int> g[N];
struct node
{
    int num, val;

    bool operator<(node b) const
    {
        if (num != b.num)
            return num < b.num;
        return val > b.val;
    }
};
struct Matrix
{
    node f[M];
    int g[M];

    Matrix()
    {
        fill(f, f + M, (node){INF, 0});
        memset(g, 0, sizeof(g));
    }

    void set(int x)
    {
        rep(i, 1, M - 1)
        {
            f[i] = {0, i - 1};
            g[i] = max(i - 1, x - 1);
        }
        f[0] = {1, x - 1};
        g[0] = x - 1;
    }

    Matrix operator*(Matrix b) const
    {
        Matrix res;
        rep(i, 0, M - 1)
        {
            res.f[i] = min((node){f[i].num + b.f[f[i].val].num, b.f[f[i].val].val}, (node){f[i].num + b.f[g[i]].num + 1, b.f[g[i]].val});
            res.g[i] = b.g[g[i]];
        }
        return res;
    }
} mat[N];
struct vect
{
    node f;
    int g;

    vect()
    {
        f = {INF, 0};
        g = 0;
    }

    void clear()
    {
        f = {0, 0};
        g = 0;
    }

    vect operator*(Matrix b) const
    {
        vect res;
        rep(i, 0, M - 1)
        {
            res.f = min((node){f.num + b.f[f.val].num, b.f[f.val].val}, (node){f.num + b.f[g].num + 1, b.f[g].val});
            res.g = b.g[g];
        }
        return res;
    }
} res;

struct segment_tree
{

#define ls p << 1
#define rs p << 1 | 1

    Matrix sum[N << 2][2];

    void build(int p, int l, int r)
    {
        if (l == r)
        {
            sum[p][0] = sum[p][1] = mat[l];
            return;
        }
        int mid = l + r >> 1;
        build(ls, l, mid);
        build(rs, mid + 1, r);
        sum[p][0] = sum[ls][0] * sum[rs][0];
        sum[p][1] = sum[rs][1] * sum[ls][1];
    }

    void update(int p, int l, int r, int x)
    {
        if (l == r)
        {
            sum[p][0] = sum[p][1] = mat[l];
            return;
        }
        int mid = l + r >> 1;
        if (mid < x)
            update(rs, mid + 1, r, x);
        else
            update(ls, l, mid, x);
        sum[p][0] = sum[ls][0] * sum[rs][0];
        sum[p][1] = sum[rs][1] * sum[ls][1];
    }

    void query(int p, int l, int r, int ll, int rr, int ty)
    {
        if (ll <= l && r <= rr)
        {
            res = res * sum[p][ty];
            return;
        }
        int mid = l + r >> 1;
        if (!ty)
        {
            if (mid >= ll)
                query(ls, l, mid, ll, rr, ty);
            if (mid < rr)
                query(rs, mid + 1, r, ll, rr, ty);
        }
        else
        {
            if (mid < rr)
                query(rs, mid + 1, r, ll, rr, ty);
            if (mid >= ll)
                query(ls, l, mid, ll, rr, ty);
        }
    }
} seg;
int fa[N], top[N], siz[N], dep[N];
int son[N], st[N], en[N], tot, rnk[N];
// bool en;

void dfs(int x, int fat)
{
    dep[x] = dep[fat] + 1;
    fa[x] = fat;
    siz[x] = 1;
    for (auto v : g[x])
    {
        if (v == fat)
            continue;
        dfs(v, x);
        siz[x] += siz[v];
        if (!son[x] || siz[son[x]] < siz[v])
            son[x] = v;
    }
}

void dfs2(int x, int fat, int tp)
{
    // cerr << x << ' ' << tp << endl;
    top[x] = tp;
    st[x] = ++tot;
    mat[tot].set(a[x]);
    rnk[tot] = x;
    if (son[x])
        dfs2(son[x], x, tp);
    for (auto v : g[x])
    {
        if (v != son[x] && v != fat)
        {
            dfs2(v, x, v);
        }
    }
    en[x] = tot;
}

int lca(int u, int v)
{
    while (top[u] != top[v])
    {
        if (dep[top[u]] < dep[top[v]])
            swap(u, v);
        u = fa[top[u]];
    }
    if (dep[u] < dep[v])
        return u;
    return v;
}

void calc(int x, int d, int ty)
{
    if (!d)
        return;
    if (dep[x] - dep[top[x]] + 1 <= d)
    {
        if (!ty)
        {
            calc(fa[top[x]], d - dep[x] + dep[top[x]] - 1, ty);
            seg.query(1, 1, n, st[top[x]], st[x], ty);
        }
        else
        {
            seg.query(1, 1, n, st[top[x]], st[x], ty);
            calc(fa[top[x]], d - dep[x] + dep[top[x]] - 1, ty);
        }
    }
    else
    {
        seg.query(1, 1, n, st[x] - d + 1, st[x], ty);
    }
}

void solve()
{
    cin >> n;
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, n - 1)
    {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1, 0);
    dfs2(1, 0, 1);
    seg.build(1, 1, n);
    int q;
    cin >> q;
    while (q--)
    {
        char c;
        int x, y;
        cin >> c >> x >> y;
        if (c == 'Q')
        {
            res.clear();
            int p = lca(x, y);
            // cerr << x << ' ' << y << ' ' << p << endl;
            calc(x, dep[x] - dep[p], 1);
            calc(fa[y], dep[y] - dep[p], 0);
            cout << res.f.num << endl;
        }
        else
        {
            a[x] = y;
            mat[st[x]].set(y);
            seg.update(1, 1, n, st[x]);
        }
    }
}

signed main()
{
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    // cerr<<(&en-&st)/1024.0/1024.0<<endl;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int testcase = 1;
    // cin >> testcase;
    while (testcase--)
        solve();
    return 0;
}

标签:return,rep,int,eg,20240130,sum,define
From: https://www.cnblogs.com/xiaruize/p/17998072

相关文章

  • 算法模板 v1.5.1.20240130
    算法模板v1.1.1.20240115:之前的历史版本已经不可寻,创建了第一份算法模板。v1.2.1.20240116:删除“编译”-“手动开栈”与“编译”-“手动开O优化”;将“编译”-“CF模板”中的第20行代码cin>>T;注释;删除“读写”及其目录下的内容;删除“图论”-“欧拉图”-“混合图”;删除“图论”-......