省选模拟测试7
期望得分:
实际得分:
今天挂了好多分,难受。
打了个 的假做法,常数巨大,被卡成了 分。
神 是关键字, 分直接被干没了。
的题,打了 分的暴力,但没开 直接炸了。
T1 发微博#
题意描述#
刚开通的 SH 微博共有 个用户( 标号),在这短短一个月的时间内,用户们活动频繁,共有 条按时间顺序的记录:
! x 表示用户 x 发了一条微博;
+ x y 表示用户 x 和用户 y 成为了好友
− x y 表示用户 x 和用户 y 解除了好友关系
当一个用户发微博的时候,所有他的好友(直接关系)都会看到他的消息。
假设最开始所有人之间都不是好友关系,记录也都是合法的(即 + x y
时 和 一定不是好友,而 − x y
时 和 一定是好友)。
问这 条记录发生之后,每个用户分别看到了多少条消息
数据范围:
solution#
可以直接拿 正着做,下面有一个比较好写的做法。
考虑如果一条关系 出现的时间为 那么 答案就要累加上 在这一段时间内发布的微博数。
正着维护前缀和的话,空间开不下。
考虑倒着做,维护一个 数组,表示从 这一段时间内 发送的微博数。
如果 在这一刻成为了好友,就让 ans[x] += sum[y],ans[y]+= sum[x]
反之解除好友就把 ans[x]-=sum[y],ans[y]-=sum[x]
然后这道题就做完了。复杂度
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
#define mp make_pair
const int N = 5e5+10;
int n,m,x,y,tot,w[N],sum[N];
struct node
{
int opt,x,y;
}q[N];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
int main()
{
n = read(); m = read();
for(int i = 1; i <= m; i++)
{
char ch; cin>>ch;
if(ch == '!')
{
q[i].x = read();
q[i].opt = 1;
}
if(ch == '+')
{
q[i].x = read();
q[i].y = read();
q[i].opt = 2;
}
if(ch == '-')
{
q[i].x = read();
q[i].y = read();
q[i].opt = 3;
}
}
for(int i = m; i >= 1; i--)
{
if(q[i].opt == 1) sum[q[i].x]++;
else if(q[i].opt == 2) w[q[i].x] += sum[q[i].y], w[q[i].y] += sum[q[i].x];
else if(q[i].opt == 3) w[q[i].x] -= sum[q[i].y], w[q[i].y] -= sum[q[i].x];
}
for(int i = 1; i <= n; i++) printf("%d ",w[i]);
printf("\n");
fclose(stdin); fclose(stdout);
return 0;
}
T2 字符串#
题意描述#
不想让家长看自己的聊天记录,所以 就想出了一套密码以及一种加密方式。
加密方式:现在给出一段英文,我们把每一个单词翻转,并将其所有的大写字母都变为小写字母,最后在把这些单词收尾相接得到一个字符串,这样我们就加密完了。举个例子 :加密后变为 。
坐在电脑屏幕另一侧的你对于 这样的行为十分恼怒,因为看不懂,但是好在 给你了他所有可能说的单词,现在你需要运用编程能力将 说的话解密。
数据范围:字符串长度 , 单词个数 , 所有单词长度 。
solution#
首先有 分的 做法,就是设 表示前 个字符能否拼接成。
转移时枚举每个单词,如果 和单词相同,则 。
同时记录一下决策点,来输出方案。
判断两个字符串是否相同,用 来判断即可。
其实我们是没必要枚举每个单词的,因为单词的长度是小于 的,所以我们只需要枚举 长度小于 的后缀即可。
众所周知 map[x]
非常慢,所以建议使用 map.find(x)
复杂度: 。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
#define ull unsigned long long
const int N = 1e5+10;
const int base = 23333;
const int p = 998244353;
int n,m,cnt;
int pos[N],f[N],pre[N],len[N];
ull has[N];
char s[N],b[100010][1010];
map<ull,int> id;
int main()
{
freopen("char.in","r",stdin);
freopen("char.out","w",stdout);
scanf("%d",&n); scanf("%s",s+1);
scanf("%d",&m);
for(int i = 1; i <= m; i++)
{
scanf("%s",b[i]+1);
int k = strlen(b[i]+1);
ull tmp = 0;
for(int j = k; j >= 1; j--)
{
if(b[i][j] < 'a') tmp = tmp * base + b[i][j] - 'A' + 'a';
else tmp = tmp * base + b[i][j];
}
if(id.find(tmp) == id.end()) id[tmp] = i;
len[i] = k;
}
f[0] = 1;
for(int i = 1; i <= n; i++)
{
ull tmp = 0, mi = 1;
for(int j = i; j >= 1 && i-j+1 <= 1000; j--)
{
tmp = tmp + s[j] * mi; mi = mi * base;
if(f[i]) break;
if(id.find(tmp) != id.end() && f[j-1] == 1)
{
f[i] = 1;
pre[i] = id[tmp];
break;
}
}
}
while(n)
{
pos[++cnt] = pre[n];
n = n-len[pre[n]];
}
for(int i = cnt; i >= 1; i--) printf("%s ",b[pos[i]]+1);
printf("\n");
fclose(stdin); fclose(stdout);
return 0;
}
T3 序列/由乃的OJ#
题意描述#
给你一个有 个点的树,每个点的包括一个位运算 和一个权值 ,位运算有 &
,|
,^
三种,分别用 1, 表示。
每次询问包含三个整数 ,初始选定一个数 。然后 依次经过从 到 的所有节点,每经过一个点 就变成 ,所以他想问你,最后到 时,希望得到的值尽可能大,求最大值。给定的初始值 必须是在 [之间。
每次修改包含三个整数 ,意思是把 点的操作修改为 ,数值改为 。
数据范围:
solution#
这个其实是起床困难综合征的树上版本。
不难想到用线段树来维护。
考虑对线段树上的每一个区间维护 个值 分别表示,每一位全为 的数,从左/右依次进行运算得到的结果。
咕咕咕。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理