Codeforces Div2 837(未完待续)
UPD 2022/12/12
昨天可能是晚上11.35风水不太好,刚考完概率论,该测测风水的。
赛上一共才过了3个题,补到了D,Bwa了一发之后,改了思路才过,然后A和C结果FST了
排个序,max一定在头和尾上
FST的原因在于 新改用的Dev C 它不提醒类型错误,然后炸两个int
相乘如果可能炸long long的话要给左边乘一个1ll,我乘到右边去了。。。。
这题本来觉得 通过递推求每个片段最大左端点和最小右端点,赛时交的代码
赛后发现其实段 和 段之间是有交的。。。。
比如:
3 1
1 3
这个东西显然 有两个段 【1 2】 【2 3】 然后我会把这个段内的东西给 记录重复,
然后就g了。。。。。赛时脑子瓦特了,这个想法应该还可以做下去,
但可能需要考虑的东西更多实际上是懒得写了bushi
然后换思路,每个位置的右边界显然有单调性
然后 每个位置算一遍就好了。
赛时脑子不好用这么简单还做了这么久
B的代码,我菜轻喷
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f;
int main(){
int t;
cin >> t;
while(t--){
int n, m;
cin >> n >> m;
vector<int> R(n + 1),L(n + 1);
for (int i = 1; i <= n; i++)R[i] = n + 1, L[i] = 0;
for (int i = 1; i <= m; i++){
int x, y;
cin >> x >> y;
if(x > y)swap(x, y);
R[x] = min(R[x], y);
L[y] = max(L[y], x);
}
ll ans = 0;
int now = n;
for (int i = n; i>= 1; i--){
if(R[i]< now + 1) now = R[i] - 1;
ans += now - i + 1;
}
cout << ans << "\n";
}
}
赛时这个题思路很清晰,
1.如果有重复的,直接是YES
2.所有小于
然后看一下每个数所含的这些因子里有无重复的。
3.每个数筛完这些之后,最多还剩一个大于
复杂度大约是
赛时调了许久的原因是 欧拉筛板子是从零开始往里放素数的,我给忘记了。
然后 赛时wa了一发,忘记想第三步了
FST 的原因是第一步忘记重复的是1的情况了。。。。
C
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
typedef long long ll;
bool isprime[maxn];
int prime[maxn];
int used[maxn];
int get_primes(int n)
{
memset(isprime, true ,sizeof(isprime));
int tot = 0;
for (int i = 2; i <= n; i++)
{
if (isprime[i]) prime[tot++] = i;
for (int j = 0; prime[j] <= n / i; j++)
//判断条件解释:我们用primes[j]筛掉合数primes[j] * i,只用筛掉小于n的合数就可以了
{
isprime[prime[j] * i] = 0;
if (i % prime[j] == 0) break;
}
}
return tot;
}
int main(){
int tot = get_primes(32000);
int t;
cin >> t;
while(t--){
int n;
cin >> n;
vector<int> a(n + 1);
map<int,int> mp;
for (int i = 1; i <= n; i++){
cin >> a[i];
if(a[i] > 1)mp[a[i]]++;
}
bool ok = 0;
for (int i = 1; i <= n; i++){
if(mp[a[i]] > 1){
ok = 1;
break;
}
}
if(ok){
cout << "YES\n";
continue;
}
mp.clear();
for (int i = 1; i <= n; i++) {
for (int j = 0; j < tot; j++){
if(a[i] % prime[j])continue;
while(a[i] % prime[j] == 0){
a[i] /= prime[j];
}
if(used[j]){
ok = 1;
break;
}
used[j] = 1;
}
if(a[i] > 1)mp[a[i]]++;
if(ok)break;
}
for (int i = 1; i <= n; i++){
if(a[i] > 1 && mp[a[i]] >= 2){
ok = 1;
break;
}
}
for (int j = 0; j < tot; j++)used[j] = 0;
if(ok){
cout << "YES\n";
continue;
}
cout << "NO\n";
}
}
D这个题属于好写不好想的DP,但我觉得还是我做的少,做多了应该不难想
-
跑LCA,枚举所有两个点之间的最短路径。
-
正序枚举长度
长度为1的情况,dp[u][v] = s[u] == s[v] ? 2 : 1;
长度大于1的情况。u1,v1分别是u相邻的u,v路径上的点 和 v相邻的u,v路径上的点。
dp[u][v] = max(dp[u1][v], dp[u][v1]);
dp[u][v] = max(dp[u][v],dp[u1][v1] + (s[u1] == s[v1] ? 2 : 0))
补题的时候,wa了几发,是因为vector忘记清空了。
D
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
const int maxn = 2e3 + 5;
int head[maxn], ecnt;
int dp[maxn][maxn];
int n;
int dep[maxn],f[maxn][30], dis[maxn][maxn];
struct edge {
int v, nxt;
}e[maxn << 1];
void add_edge(int u,int v) {
ecnt++;
e[ecnt].nxt = head[u];
e[ecnt].v = v;
head[u] = ecnt;
}
void dfs(int p = 1, int fa = 0) {
for (int i = head[p]; i != -1; i = e[i].nxt) {
int u = e[i].v;
if (u != fa) {
dep[u] = dep[p] + 1;
f[u][0] = p;
dfs(u, p);
}
}
}
void init_lca() {
for (int i = 1; i < 18; i++) {
for (int j = 1; j <= n; j++) {
f[j][i] = f[f[j][i - 1]][i - 1];
}
}
}
int lca(int a, int b) {
if (dep[a] < dep[b])swap(a, b);
int h = dep[a] - dep[b];
for (int i = log2(maxn - 5); i >= 0; i--) {
if (h >= (1 << i))
a = f[a][i], h -= (1 << i);
}
if (a == b)return a;
for (int i = log2(maxn - 5); i >= 0; i--) {
if (f[a][i] != f[b][i])a = f[a][i], b = f[b][i];
}
return f[a][0];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
vector<P> with_dis[maxn];
memset(head, -1, sizeof(head));
//memset(dep, 0, sizeof dep);
//memset(f,0,sizeof f);
ecnt = 1;
dep[1] = 1;
cin >> n;
string s;
cin >> s;
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
add_edge(a, b);
add_edge(b, a);
}
dfs();
init_lca();
//memset(dis, 0, sizeof dis);
for (int u = 1; u <= n; u++){
dp[u][u] = 1;
for (int v = u + 1; v <= n; v++){
int x = lca(u, v);
dis[u][v] = dis[v][u] = -dep[x] * 2 + dep[u] + dep[v] ;
with_dis[dis[u][v]].push_back(make_pair(u, v));
}
}
for (int len = 1; len <= n; len++){
for (auto now : with_dis[len]){
int u = now.first, v = now.second;
if(len == 1){
if(s[u - 1] == s[v - 1])dp[u][v] = dp[v][u] = 2;
else dp[u][v] = dp[v][u]= 1;
}
else {
int u1 = -1, v1 = -1;
for (int i = head[u]; i != -1; i = e[i].nxt){
if(dis[e[i].v][v] < dis[u][v]){
u1 = e[i].v;
break;
}
}
for (int i = head[v]; i != -1; i = e[i].nxt) {
if(dis[u][e[i].v] < dis[u][v]){
v1 = e[i].v;
break;
}
}
dp[u][v] = dp[v][u] = dp[u1][v1] + (s[u - 1] == s[v - 1] ? 2 : 0);
//if(u == 3 && v == 5) cout << s[u - 1] << s[v - 1] << u1 << v1<< endl;
dp[u][v] = dp[v][u] = max(dp[u1][v], dp[u][v]);
dp[u][v] = dp[v][u] = max(dp[u][v1], dp[u][v]);
}
}
}
int ans = 0;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
//cout << dp[i][j] << endl;
ans = max(dp[i][j], ans);
}
}
cout << ans << endl;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App