Codeforces Round 997 (Div. 2)

A. Shape Perimeter

题意:一个m×m的印章每次往右上方向移动,问盖出来的图形周长。

假设每次都能盖m×m的格子,那么看每两次盖章有多重复的减去就行。第i次移动了xi,yi,那么就会有一个mxi,myi的矩形被重复覆盖,减去它的周长。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> x(n), y(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> x[i] >> y[i];
    }

    i64 ans = m * 4 * n;
    for (int i = 1; i < n; ++ i) {
    	ans -= (m - x[i] + m - y[i]) * 2;
    }

    std::cout << ans << "\n";
}

B. Find the Permutation

题意:有一个排列,给你一个矩阵表示y是否在x后面(y>x), 求出这个排列。

对于每一对xy,我们都可以知道谁在前面,前面的向后面连边,那么没入度的点就是第一个,依次推出其他点的位置。用拓扑排序即可。
因为我们知道每个数有几个在他前面,那么位置也确定了,赛时没想这么多,其实不用拓扑排序。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<std::string> s(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> s[i];
    }

    std::vector<std::vector<int> > adj(n);
    std::vector<int> in(n);
    for (int i = 0; i < n; ++ i) {
    	for (int j = i + 1; j < n; ++ j) {
    		if (s[i][j] == '1') {
    			adj[i].push_back(j);
    			++ in[j];
    		} else {
    			adj[j].push_back(i);
    			++ in[i];
    		}
    	}
    }

    std::queue<int> q;
    std::vector<int> ans;
    for (int i = 0; i < n; ++ i) {
    	if (in[i] == 0) {
    		q.push(i);
    	}
    }

    while (q.size()) {
    	int u = q.front(); q.pop();
    	ans.push_back(u);
    	for (auto & v : adj[u]) {
    		if ( -- in[v] == 0) {
    			q.push(v);
    		}
    	}
    }

    for (auto & x : ans) {
    	std::cout << x + 1 << " \n"[x == ans.back()];
    }
}

C. Palindromic Subsequences

题意:构造一个数组使得长度最长的最长回文子序列数量最多。

如果我们填1~n3,后面三个填1,2,3。你们发现会有3(n4)个最长回文子序列。当n大于6的时候满足3(n4)>nn等于6我直接抄的样例。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    if (n == 6) {
    	std::cout << 1 << " " << 1 << " " << 2 << " " << 3 << " " << 1 << " " << 2 << "\n";
    	return;
    }
    int m = n - 3;
    for (int i = 1, x = 0; i <= n; ++ i) {
    	std::cout << x + 1 << " \n"[i == n];
    	x = (x + 1) % m;
    }
}

D. Unique Median

不会。坐了两个小时牢

题意:如果一个数组长度为奇数,或者长度是偶数以及两个中位数相等,就是好的。给你一个数组,求有多少个子数组是好的。

这题我们反着做,求出有多少不好的子数组,然后用总数减去就是答案。
什么样的数组是不好的?恰好有一个x满足1x的总个数是len2。如果让ai<=x时,bi=1,让ai>x时,bi=1,那么一个子数组是坏的代表它的和为0。那么我们枚举这个x,看有多少个值为0的子数组。
sumi为枚举xi=1ibi,那么我们需要减去一个sumj,满足sumisumj=0,意为所有[j+1,i]是坏的j。但要注意有可能区间里没有x,那么不应该算这个区间。比如我们枚举x=4时,[1,2,6,6]的确是坏的,但后面枚举x=5时,我们又会算一遍,这个数组应该只在x=2时算一遍。所以我们要在出现一个x时再把没加进来的sum加进来。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    i64 ans = (i64)n * (n + 1) / 2;
    for (int x = 1; x <= 10; ++ x) {
        std::vector<int> sum(n + 1);
        for (int i = 0; i < n; ++ i) {
            sum[i + 1] = sum[i] + (a[i] > x ? 1 : -1);
        }

        std::vector<int> cnt(2 * n + 1);
        for (int i = 1, j = 0; i <= n; ++ i) {
            if (a[i - 1] == x) {
                while (j < i) {
                    ++ cnt[sum[j] + n];
                    ++ j;
                }
            }

            ans -= cnt[sum[i] + n];
        }
    }

    std::cout << ans << "\n";
}
posted @   maburb  阅读(124)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示