2022年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛

比赛链接

2022年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛

G.天气预报

给定一个01串,找到有多少个至少包含a个0,b个1的子串
image

解题思路

双指针

可以发现,对于一个位置来说,其往左满足至少有 a0 且至少有 b1 的位置 p 是确定的,且当前位置右移时,p 至少不会左移

  • 时间复杂度:O(n)

代码

// Problem: 天气预报 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/30532/G // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } int n,a,b; LL res; int main() { cin>>n>>a>>b; string s; cin>>s; s=' '+s; for(int i=1,cnt0=0,cnt1=0,l=1;i<=n;i++) { if(s[i]=='0')cnt0++; else cnt1++; while(l<i) { if(s[l]=='0') { if(cnt0>a)l++,cnt0--; else break; } else { if(cnt1>b)l++,cnt1--; else break; } } if(cnt0>=a&&cnt1>=b)res+=l; } cout<<res+(a==0&&b==0); return 0; }

L.剪绳子

题目描述

Wiki是电视节目《超级大脑》的忠实粉丝,几乎每期必看。最近节目组发明了一个新的记忆游戏,Wiki积极报名,居然成功入选了!

新的游戏规则很简单,但需要选手有超强的数字记忆能力。主持人会取来一根十米长的绳子,将它水平粘在一块平板上,则此时这根绳子可以视为一根单位为米的坐标轴,左侧一端为0,右侧一端为10。然后每隔10秒种主持人会发布一条命令,命令分两种,"剪"和"答"。如果主持人命令"剪",现场工作人员会随机在绳子上任意剪一刀(但他当然不会去剪已经剪过的地方或者剪绳子的两端)。每次剪完后绳子依然像最初那样固定在平板上,只不过剪断的地方多了一道痕迹,并且绳子的段数增加了1。此时在平板上的测量仪器会对这一次剪断位置的坐标进行测量,并将该坐标显示在屏幕上,直到主持人喊出下一次命令才会消失。由于这台仪器十分精密,它的每次测量都会精确到小数点后五位。如果主持人喊出"答",则屏幕上会随机显示一个坐标(也是保留五位小数),要求Wiki在10秒内答出该坐标目前所在的一段绳子有多长。这里保证屏幕上的数字不会出现刚才剪断过的位置坐标。

Wiki对自己的记忆力信心满满,因此接受了挑战。但他很快发现这个游戏没有那么简单,大量的数字很容易被搞混,因此求助于拥有高超编程技能的你。

输入描述:

第一行输入一个正整数q,表示主持人有q个命令。
接下来q行,每行输入一条命令。命令有两种格式:

  1. C f:f是一个浮点数,且严格保留五位小数。该命令表示主持人要求现场工作人员剪绳子,并且屏幕上显示剪断位置的坐标为f;

  2. A f:f是一个浮点数,且严格保留五位小数。该命令表示屏幕上显示了一个数f,要求Wiki回答出f所在的一段绳子长度为多少。这里要求"一段绳子"左右端点都是被剪断过的位置或者是初始绳子的左右端点之一(即坐标0.00000和10.00000的位置),且这一段绳子内部没有被剪断过的地方。

输出描述:

对于每个"答"的要求,要求输出屏幕显示的坐标所在的一段绳子的长度,保留五位小数。

示例1

输入

4 C 5.32145 A 4.00000 C 6.13745 A 6.00000

输出

5.32145 0.81600

备注:
image

解题思路·

并查集

将每个实数看作一个点,为了达到精度要求,共 10000001 个点,将所有点按剪的位置合并,记录每个点的集合大小,逆序处理询问,当剪操作时,合并两端,合并后表示剪操作后之前的那段就复原了,询问就输出所在集合的大小

  • 时间复杂度:O(107)

set,二分

使用set维护剪的位置,然后每次询问,找到当前位置位于哪两个剪的位置之间,两个位置之间的长度即为答案,注意有可能询问端点处的长度

  • 时间复杂度:O(nlogn)

代码

  • 并查集
// Problem: 剪绳子 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/30532/L // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair #define eps 1e-6 using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e7+5; int fa[N],n,s[N]; vector<int> v; struct A { int op; double x; }a[100005]; int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } void merge(int x,int y) { x=find(x),y=find(y); fa[x]=y; s[y]+=s[x]; } int main() { cin>>n; for(int i=0;i<N;i++)fa[i]=i,s[i]=1; for(int i=1;i<=n;i++) { char c; cin>>c>>a[i].x; a[i].op=c=='C'?1:0; if(c=='C'&&fabs(a[i].x-0)>eps&&fabs(a[i].x-10)>eps) v.pb(a[i].x*1000000); } sort(v.begin(),v.end()); for(int i=1,j=0;i<=10000000;i++) { if(j<v.size()&&v[j]==i) { // cout<<v[j]<<' '; j++; continue; } merge(i,i-1); } vector<int> res; for(int i=n;i;i--) { if(a[i].op)merge(a[i].x*1000000,a[i].x*1000000-1); else res.pb(s[find(a[i].x*1000000)]); } for(int i=res.size()-1;i>=0;i--)printf("%.5lf\n",res[i]/1000000.); return 0; }
  • set
// Problem: 剪绳子 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/30532/L // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair #define eps 1e-8 using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } int t; set<int> s; int main() { s.insert(0); s.insert(10000000); for(cin>>t;t;t--) { char op; double x; cin>>op>>x; if(op=='C')s.insert(x*1000000); else { if(fabs(x)<eps||fabs(x-10.)<eps) { if(fabs(x)<eps)printf("%.5lf\n",*(++s.begin())/1000000.); else { auto p=--s.end(); auto pp=--p; printf("%.5lf\n",(10000000-(*pp))/1000000.); } continue; } auto t=s.lower_bound(x*1000000); auto tt=t; tt--; printf("%.5lf\n",((*t)-(*tt))/1000000.); } } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16064908.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(403)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示