csp复建记录

202104

2.邻域均值

通过题目限制得出 \(x, y\) 的范围,二维前缀和统计即可。

#include <bits/stdc++.h>
using namespace std;
int n, L, r, cnt, a[700][700], sum[700][700];
double ans, t;
int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n >> L >> r >> t;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> a[i][j];
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
        }
    } 
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            int ex = min(n, i + r), ey = min(n, j + r), sx = max(1, i - r), sy = max(1, j - r);
            ans = 1.0 * (sum[ex][ey] - sum[ex][sy - 1] - sum[sx - 1][ey] + sum[sx - 1][sy - 1]) / ((ex - sx + 1) * (ey - sy + 1));
            if (ans <= t) cnt++;
        }
    }
    cout << cnt << "\n";
	return 0;
}

202109

2.非零段划分

提前记录下来每个值出现过的位置。依次增加 \(p\) 的值,每次找到 \(n\) 个数中等于 \(p\) 的值的位置能产生的贡献(和左右两边 \(0\) 的出现情况有关)。

#include <bits/stdc++.h>
const int N = 5e5 + 5;
const int M = 1e4 + 5;
using namespace std;

int n, ans, maxx, a[N];
vector<int> f[M];

int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        f[a[i]].push_back(i);
        if (a[i] == 0) {
            if (cnt > 0) {
                ans++;
                cnt = 0;
            }
        }
        else cnt++;
    }
    if (cnt > 0) ans++;
    maxx = max(maxx, ans);
    for (int i = 1; i <= M - 5; i++) {
         for (auto pos : f[i]) {
             a[pos] = 0;
             if (pos == 1 && a[pos + 1] == 0) ans--;
             else if (pos == n && a[pos - 1] == 0) ans--;
             else {
                if (a[pos - 1] == 0 && a[pos + 1] == 0) ans--;
                else if (a[pos - 1] != 0 && a[pos + 1] != 0) ans++;
             }
         }
         maxx = max(maxx, ans);
    }
    cout << maxx << endl;
	return 0;
}

202112

2.序列查询新解

不难发现 \(g(x)\)\(r\) 个增加 \(1\),故可以按段来统计,注意边界情况的讨论。

202203

2.出行计划

由题意不难得到有效条件的区间,差分即可。注意双边不等式的左边可能会小于 \(0\) ,可以通过整体平移的方式(或者和 \(0\)max 的方法)。

#include <bits/stdc++.h>
const int lim = 2e5 + 5;
using namespace std;

int n, m, k, t, c, x, d[lim << 1];

int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++) {
        cin >> t >> c;
        d[(lim - 5) + t - c - k + 1]++;
        d[(lim - 5) + t - k + 1]--;
    }
    for (int i = 0; i <= (lim - 5) << 1; i++) d[i] += d[i - 1];
    for (int i = 1; i <= m; i++) {
        cin >> x;
        cout << d[(lim - 5) + x] << endl;
    }
	return 0;
}

202206

2.寻宝!大冒险!

把大地图中每个为 \(1\) 的点记录下来,用相对坐标依次进行比对,统计即可。

#include <bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
const int N = 100;
using namespace std;

int n, L, S, x, y, ans, b[N][N];
vector<pair<int, int> > a, dir;
map<pair<int, int>, int> mapp;

bool check(pair<int, int> u, pair<int, int> v) { 
    int dx = u.fi + S + 1, dy = u.se + S + 1;
    if (dx > L + 1 || dy > L + 1) return true;
    int x = u.fi + v.fi, y = u.se + v.se;
    return b[v.fi][v.se] ^ mapp[mp(x, y)];
}

int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n >> L >> S;
    for (int i = 1; i <= n; i++) {
        cin >> x >> y;
        mapp[mp(x, y)]++;
        a.push_back(mp(x, y));
    }
    for (int i = 0; i <= S; i++) {
        for (int j = 0; j <= S; j++) {
            cin >> b[i][j];
        }
    }
    for (int j = 0; j <= S; j++) {
        for (int i = 0; i < S / 2 + 1; i++) swap(b[i][j], b[S - i][j]);
    }
    for (int i = 0; i <= S; i++) {
        for (int j = 0; j <= S; j++) {
            if (i == 0 && j == 0) continue;
            dir.push_back(mp(i, j));
        }
    }
    for (auto now : a) {
        bool flag = true;
        for (auto dxy : dir) {
            if (check(now, dxy)) {
                flag = false;
                break;
            }
        }
        if (flag) ans++;
    }
    cout << ans << endl;
	return 0;
}

3.角色授权

STL 无脑叠 log, 喜提 70pts.

#include <bits/stdc++.h>
const int N = 1e5;
using namespace std;

int n, m, q, x, id, id1, id2, ido, idc, idr;
string ch_name, opt, cls, rnm, name, uname, gname, opname, rcls, rname, ss;
map<string, int> mapp, oplist, clslist, rnmlist, ulist, glist;
map<int, int> spe1, spe2, ch_opt[N], ch_cls[N], ch_rnm[N], uright[N], gright[N];
vector<string> ucon[N], gcon[N], ori[N]; 

int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n >> m >> q;
    while (n--) {
        cin >> ch_name;
        mapp[ch_name] = ++id;
        cin >> x;
        while (x--) {
            cin >> opt;
            if (!oplist[opt]) oplist[opt] = ++ido;
            ch_opt[id][oplist[opt]] = 1;
            if (opt == "*") spe1[id] = 1;
        }
        cin >> x;
        while (x--) {
            cin >> cls;
            if (!clslist[cls]) clslist[cls] = ++idc;
            ch_cls[id][clslist[cls]] = 1;
            if (cls == "*") spe2[id] = 1;
        }
        cin >> x;
        while (x--) {
            cin >> rnm;
            if (!rnmlist[rnm]) rnmlist[rnm] = ++idr;
            ch_rnm[id][rnmlist[rnm]] = 1;
        }
    }
    while (m--) {
        cin >> ch_name >> x;
        while (x--) {
            cin >> ss >> name;
            if (ss == "u") {
                if (!ulist[name]) ulist[name] = ++id1;
                uright[mapp[ch_name]][ulist[name]] = 1;
                ucon[ulist[name]].push_back(ch_name);
            }
            else {
                if (!glist[name]) glist[name] = ++id2;
                gright[mapp[ch_name]][glist[name]] = 1;
                gcon[glist[name]].push_back(ch_name);
            }
        }
    }
    while (q--) {
        cin >> uname >> x;
        if (!ulist[uname]) ulist[uname] = ++id1;
        while (x--) {
            cin >> gname;
            if (!glist[gname]) glist[gname] = ++id2;
            ori[ulist[uname]].push_back(gname);
        }
        bool flag = 0;
        cin >> opname >> rcls >> rname;
        for (auto ch_name : ucon[ulist[uname]]) {
            if (uright[mapp[ch_name]][ulist[uname]]) {
                if (ch_opt[mapp[ch_name]][oplist[opname]] || spe1[mapp[ch_name]]) {
                     if (ch_cls[mapp[ch_name]][clslist[rcls]] || spe2[mapp[ch_name]]) {
                         if (ch_rnm[mapp[ch_name]].empty() || ch_rnm[mapp[ch_name]][rnmlist[rname]]) {
                            flag = 1;
                         }
                     }
                }
            }
        }
        if (flag == 0) {
            for (auto gname : ori[ulist[uname]]) {
                for (auto ch_name : gcon[glist[gname]]) {
                    if (gright[mapp[ch_name]][glist[gname]]) {
                        if (ch_opt[mapp[ch_name]][oplist[opname]] || spe1[mapp[ch_name]]) {
                            if (ch_cls[mapp[ch_name]][clslist[rcls]] || spe2[mapp[ch_name]]) {
                                if (ch_rnm[mapp[ch_name]].empty() || ch_rnm[mapp[ch_name]][rnmlist[rname]]) {
                                    flag = 1;
                                }
                            }
                        }
                    }
                }
            }
        }
        cout << flag << endl;
        ori[ulist[uname]].clear();
    }
	return 0;
}

202209

2.何以包邮

70pts 二进制枚举,100pts 完全背包。

#include <bits/stdc++.h>
const int lim = 3e5 + 5;
using namespace std;

int n, m, sum, a[50], f[lim];

int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];
    f[0] = 1;
    for (int i = 1; i <= n; i++) {
        sum += a[i];
        for (int j = lim - 5; j >= a[i]; j--) f[j] |= f[j - a[i]];
    }
    for (int i = m; i <= sum; i++) {
        if (f[i]) {
            cout << i << endl;
            return 0;
        }
    }
	return 0;
}

202212

训练计划

建正图反图分别跑一遍。

#include <bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
const int N = 5050;
using namespace std;

bool flag;
int n, m, x, maxx, in[N], nin[N], ans[N], a[N];
vector<int> g[N], ng[N];
queue<pair<int, int> > q;

void dfs(int x) {
    for (auto to : ng[x]) {
        ans[to] = min(ans[to], ans[x] - a[to]);
        dfs(to);
    }
}

int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> x;
        if (x) {
            g[x].push_back(i);
            in[i]++;
            ng[i].push_back(x);
            nin[x]++;
        }
    }
    for (int i = 1; i <= m; i++) cin >> a[i];
    for (int i = 1; i <= m; i++) {
        if (in[i] == 0) q.push(mp(i, 1));
    }
    while (!q.empty()) {
        auto now = q.front();
        q.pop();
        int u = now.fi, w = now.se;
        ans[u] = w;
        maxx = max(maxx, ans[u]);
        if (ans[u] + a[u] - 1 > n) flag = 1;
        for (auto v : g[u]) {
            if (--in[v] == 0) q.push(mp(v, ans[u] + a[u]));
        }
    }
    for (int i = 1; i <= m; i++) cout << ans[i] << (i == m ? "\n" : " ");
    memset(ans, 0x3f, sizeof(ans));
    if (!flag) {
        for (int i = 1; i <= m; i++) {
            if (nin[i] == 0) q.push(mp(i, n - a[i] + 1));
        }
        while (!q.empty()) {
            auto now = q.front();
            q.pop();
            ans[now.fi] = now.se;
            dfs(now.fi);
        }
        for (int i = 1; i <= m; i++) cout << ans[i] << (i == m ? "\n" : " ");
    }
	return 0;
}

202305

2.矩阵运算

通过交换相乘的次序,化简时间复杂度。

#include <bits/stdc++.h>
const int N = 10500;
const int D = 25;
using namespace std;

int n, d, w[N], q[N][D], k[N][D], v[N][D], tk[D][N];
long long kv[N][N], ans[N][D];

int main() {
    ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	freopen("in","r", stdin);
    cin >> n >> d;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= d; j++) cin >> q[i][j];
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= d; j++) {
            cin >> k[i][j];
            tk[j][i] = k[i][j];
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= d; j++) cin >> v[i][j];
    }
    for (int i = 1; i <= n; i++) cin >> w[i];
    //d * n * n * d
    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= d; i++) {
            for (int j = 1; j <= d; j++) kv[i][j] += 1ll * tk[i][k] * v[k][j];
        }
    }
    //n * d * d * d
    for (int k = 1; k <= d; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= d; j++) ans[i][j] += 1ll * q[i][k] * kv[k][j];
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= d; j++) ans[i][j] = 1ll * ans[i][j] * w[i];
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= d; j++) cout << ans[i][j] << (j == d ? "\n" : " ");
    }
	return 0;
}

202309

2.坐标变换(其二)

由于每次操作中的 \(x, y\) 伸缩倍数一样,即若单独考虑经过所有的伸缩操作后,\((x, y)\) 变成了 \((x', y')\), 不难得出 \(\frac{y'}{x'} = \frac{y}{x}\)。同时发现逆时针旋转的操作的角度可以叠加,故用一个前缀积数组存伸缩操作,一个前缀和数组存旋转操作,最终依次直接计算即可。

#include <bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
const int N = 1e5 + 5;
const int INF = 1 << 30;
using namespace std;

int n, m, opt, i, j;
double x, y, mul[N], sum[N];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> m;
	mul[0] = 1.0;
	for (int i = 1; i <= n; i++) {
		cin >> opt >> x;
		if (opt == 1) {
			mul[i] = mul[i - 1] * x;
			sum[i] = sum[i - 1];
		}
		else {
			mul[i] = mul[i - 1];
			sum[i] = sum[i - 1] + x;
		}
	}
	while (m--) {
		cin >> i >> j >> x >> y;
		double nowk = mul[j] / mul[i - 1], nowth = sum[j] - sum[i - 1], ncos = cos(nowth), nsin = sin(nowth);
		printf("%lf %lf\n", nowk * (x * ncos - y * nsin), nowk * (x * nsin + y * ncos));
	}
	return 0;
}
posted @ 2023-09-20 09:23  BeyondLimits  阅读(10)  评论(0编辑  收藏  举报