首页 > 其他分享 >UESTC 2023 Summer Training #02 Div.2

UESTC 2023 Summer Training #02 Div.2

时间:2023-07-11 22:23:56浏览次数:45  
标签:02 Summer Training le const 10 int include define

Preface

都给我丑完了这怎么办啊, 被血虐了苦路西

这场本来前面感觉都还可以,但是当中期看了眼C的题意后准备开C后就不对劲了起来

最后1h扔掉一直T的C题去做H,结果因为被卡自然溢出的Hash一直挂到比赛结束,直接红温

感觉这场策略问题挺大的,比如没有跟榜去写更加简单的E题(比赛的时候题目都没看),以及没有考虑到自然溢出会被卡的那么惨(原来卡自然溢出的数据怎么调seed都是木大的)

嘛不过就当长个教训了的说,由于今天晚上10:30还有三小时的CF,所以B题就留着以后补了


A. Division

Prob

给定\(p,q\),求一个最大的\(x\)使得\(x|p\and q\nmid x\)

\(p\le 10^{18},q\le 10^9\)

Tutorial

首先不难发现当\(q\nmid p\)时答案就是\(p\),否则我们考虑令\(t=\frac{p}{q}\)

考虑最后答案的\(x\)满足存在一个\(y\),使得\(x\times y=p=q\times t\),由于要让\(x\)最大且不为\(q\)的倍数,那么很容易想到只要在某个质因数\(p_i\)下,我们让\(x\)关于\(p_i\)的次数比\(q\)小\(1\),就能在满足要求的前提下最大化\(x\)

说起来可能有点抽象,但手玩一下发现是很显然的

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<algorithm>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
int t,p,q;
signed main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%lld",&t);t;--t)
	{
		if (scanf("%lld%lld",&p,&q),p%q) { printf("%lld\n",p); continue; }
		int ret=1,t=p/q,rs=t,tmp=q; for (RI i=2;i*i<=tmp;++i) if (tmp%i==0)
		{
			while (tmp%i==0) tmp/=i; int cur=q/i,coef=1;
			while (t%i==0) t/=i,coef*=i; ret=max(ret,cur*(rs/coef));
		}
		if (tmp!=1)
		{
			int cur=q/tmp,coef=1;
			while (t%tmp==0) t/=tmp,coef*=tmp; ret=max(ret,cur*(rs/coef));
		}
		printf("%lld\n",ret);
	}
	return 0;
}

B. Logistical Questions

Prob

给出一个\(n\)个点,点权为\(a_i\)的树,每条边有边权,同时定义\(x,y\)之间的距离为\(dist(x,y)\)

令\(f(x)=\sum_{y=1}^n a_y\times dist(x,y)^{\frac{3}{2}}\),求使得\(f(x)\)最小的\(x\)

\(n\le 2\times 10^5\)

Tutorial

先坑着,是道找性质+点分治的题,3000分感觉还是挺神的


C. Lucky Array

Prob

定义一个数\(x\)是good的当且仅当\(x\)的所有数位在十进制下都是\(4\)或者\(7\)

给出一个长度为\(n\)的序列,要对其进行\(m\)次操作,每次操作为:

  • 区间加上某数\(c\),其中\(c\ge 1\),保证任何时候序列中的所有数均\(\le 10000\)
  • 区间询问good的数的个数

\(n,m\le 10^5\)

Tutorial

首先观察到数的可能值域很小,因此我们跑个暴力发现\([1,10000]\)内good的数只有\(30\)个

这就允许我们用暴力一点的方法,枚举每个good的数,求出最后等于它的数的个数,最后累加即可

设枚举的good数为\(lim\),则显然若一个数在某时刻\(>lim\)了则它一定不会产生任何贡献了

那么我们不妨在这种情况下暴力把这个点删掉,由于删掉一个点最多会影响\(O(\log n)\)个点,因此复杂度是有保障的

而最后询问的时候我们只关心所有值恰好为\(lim\)的数的个数,用经典套路转化一下,不难发现只要记录一下区间最大值和最大值的个数即可

那么这题就做完了,复杂度\(O(30\times n\log n)\),但是由于我的线段树不知道为什么常数一般是别人的好几倍(主要是用class套结构体),所以只能卡着原题的时限过去

实际实现的时候还有一个优化就是记录下当前第一个大于每个数的good数是什么,可以大大优化常数

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<algorithm>
#define RI register int
#define CI const int&
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
const int N=100005;
int t,rst[N],cnt,n,m,a[N],opt[N],ans[N],l[N],r[N],c[N],lim; char s[10];
class Segment_Tree
{
	private:
		struct segment
		{
			pi mx; int tag;
		}node[N<<2];
		#define MX(x) node[x].mx
		#define T(x) node[x].tag
		#define TN CI now=1,CI l=1,CI r=n
		#define LS now<<1,l,mid
		#define RS now<<1|1,mid+1,r
		inline pi merge(const pi& A,const pi& B)
		{
			if (A.fi>B.fi) return A; else
			if (A.fi<B.fi) return B; else
			return pi(A.fi,A.se+B.se);
		}
		inline void pushup(CI now)
		{
			MX(now)=merge(MX(now<<1),MX(now<<1|1));
		}
		inline void apply(CI now,CI mv)
		{
			T(now)+=mv; MX(now).fi+=mv;
		}
		inline void pushdown(CI now)
		{
			if (T(now)) apply(now<<1,T(now)),apply(now<<1|1,T(now)),T(now)=0;
		}
	public:
		inline void build(TN)
		{
			T(now)=0; if (l==r) return (void)(MX(now)=pi(a[l]<=lim?a[l]:-1e9,1));
			int mid=l+r>>1; build(LS); build(RS); pushup(now);
		}
		inline void modify(CI beg,CI end,CI mv,TN)
		{
			if (beg<=l&&r<=end) return apply(now,mv); int mid=l+r>>1; pushdown(now);
			if (beg<=mid) modify(beg,end,mv,LS); if (end>mid) modify(beg,end,mv,RS); pushup(now);
		}
		inline pi query(CI beg,CI end,TN)
		{
			if (beg<=l&&r<=end) return MX(now); int mid=l+r>>1; pi ret=pi(-1e9,0); pushdown(now);
			if (beg<=mid) ret=merge(ret,query(beg,end,LS)); if (end>mid) ret=merge(ret,query(beg,end,RS)); return ret;
		}
		inline void rebuild(TN)
		{
			if (MX(now).fi<=lim) return; if (l==r) return (void)(MX(now)=pi(-1e9,1));
			int mid=l+r>>1; pushdown(now); rebuild(LS); rebuild(RS); pushup(now);
		}
		#undef MX
		#undef T
		#undef TN
		#undef LS
		#undef RS
}SEG;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	auto calc=[&](int x)
	{
		while (x>0)
		{
			if (x%10!=4&&x%10!=7) return 0;
			x/=10;
		}
		return 1;
	};
	RI i,j; for (i=1;i<=10000;++i) if (calc(i)) rst[++cnt]=i;
	//for (printf("%d\n",cnt),i=1;i<=cnt;++i) printf("%d%c",rst[i]," \n"[i==cnt]);
	for (scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",&a[i]);
	for (i=1;i<=m;++i)
	if (scanf("%s%d%d",s+1,&l[i],&r[i]),s[1]=='a') scanf("%d",&c[i]),opt[i]=1;
	for (j=1;j<=cnt;++j)
	{
		for (lim=rst[j],SEG.build(),i=1;i<=m;++i)
		if (opt[i]) SEG.modify(l[i],r[i],c[i]),SEG.rebuild(); else
		{
			pi tmp=SEG.query(l[i],r[i]);
			if (tmp.fi==lim) ans[i]+=tmp.se;
		}
	}
	for (i=1;i<=m;++i) if (!opt[i]) printf("%d\n",ans[i]);
	return 0;
}

D. Is It a Cat?

Prob

不想翻译了总之是个签到题

Tutorial

我发现我完全没有在所有题目中一眼看出签到题的能力的说

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=55;
int t,n,a[N],b[N]; char s[N];
int main()
{
	//reopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i; bool flag=1; for (scanf("%d%s",&n,s+1),i=1;i<=n;++i)
		if (s[i]=='m'||s[i]=='M') a[i]=1; else
		if (s[i]=='e'||s[i]=='E') a[i]=2; else
		if (s[i]=='o'||s[i]=='O') a[i]=3; else
		if (s[i]=='w'||s[i]=='W') a[i]=4; else flag=0;
		if (!flag) { puts("NO"); continue; }
		for (i=1;i<=n;++i) b[i]=a[i];
		for (sort(b+1,b+n+1),i=1;i<=n;++i)
		if (a[i]!=b[i]) flag=0;
		if (unique(b+1,b+n+1)-b-1<4) flag=0;
		puts(flag?"YES":"NO");
	}
	return 0;
}

E. Merge Sort

Prob

给定\(n,k\),构造一个长为\(n\)的排列\(a_n\),使得对这个序列调用归并排序时调用函数的次数恰好为\(k\)

\(n\le 10^5,k\le 2\times 10^5\)

Tutorial

原来是个丁真题,比赛的时候吊死在C和H上了题目都没看

首先因为除了第一次外面的调用外,里面的调用一定是一次调用两次的,因此若\(2|k\)则无解

否则我们总是贪心地让外面大的区间要进行交换,比如现在又区间\(1,2,3,4,5,6\),如果要让它需要调用归并排序并且满足两个子区间都还是保持有序

我们只需要交换两个子区间相邻的元素即可,即将其变成\(1,2,4,3,5,6\),然后递归处理即可

注意一下由于这里它的区间定义是左闭右开,而且下标从\(0\)开始,简直和我是完全的反面,所以要特别注意的说

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,k,a[N];
inline void solve(CI l,CI r)
{
	if (!k||r-l<=1) return; k-=2; int mid=l+r>>1;
	swap(a[mid-1],a[mid]); solve(l,mid); solve(mid,r);
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (scanf("%d%d",&n,&k),i=0;i<n;++i) a[i]=i+1;
	if (k%2==0) return puts("-1"),0; --k; solve(0,n);
	if (k) return puts("-1"),0;
	for (i=0;i<n;++i) printf("%d ",a[i]);
	return 0;
}

F. Guess the K-th Zero (Easy version)

Prob

交互题,有一个长度为\(n\)的数组\(a_n\),每个元素的值未知,但取值只能为\(0/1\)

可以进行不超过\(20\)次询问,询问的格式为一个区间\([l,r]\),每次交互器会返回这个区间内\(1\)的个数

求序列中第\(k\)个\(0\)的位置

\(n\le 2\times 10^5\)

Tutorial

这个数据范围一眼二分,设询问\([1mid]\)后得到的返回值为\(x\),则说明\([1,mid]\)中有\(mid-x\)个\(0\)

然后就根据这个和\(k\)的大小关系移动端点即可,主要可能是为了让大家知道有交互题这么一个东西所以选的这题吧

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
int n,t,k;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	scanf("%d%d%d",&n,&t,&k); int l=1,r=n,mid,ret; while (l<=r)
	{
		mid=l+r>>1; printf("? %d %d\n",1,mid);
		fflush(stdout); int x; scanf("%d",&x);
		if (mid-x>=k) ret=mid,r=mid-1; else l=mid+1;
	}
	return printf("! %d\n",ret),fflush(stdout),0;
}

G. Sum Over Zero

Prob

给定一个长为\(n\)的序列\(\{a_n\}\),你需要将其划分为若干个区间,满足:

  • 区间之间彼此不交
  • 每个区间\([l,r]\)的元素和均\(\ge 0\)

求所有合法的划分方案中,所有区间的长度之和的最大值

\(n\le 2\times 10^5,a_i\in[-10^9,10^9]\)

Tutorial

感觉最没啥思维含量的一题,好像是这场想+写花的时间最短的一题,也是拿到了这两天的唯一一个一血

首先经典设\(f_{i}\)表示钦定选择了以\(i\)为右端点的区间,此时\([1,i]\)中所有取法的最大值

同时设\(g_i\)表示\([1,i]\)中所有取法的最大值,和\(f_i\)的区别是不强制\(i\)入选,则有\(g_i=\max_\limits{1\le j\le i} f_j\)

考虑\(f_i\)的转移,显然朴素的想法就是枚举\(j<i\),若可以从\(g_j\)处转移来,则需满足\(pfx_i-pfx_{j}\ge 0\)

,此时\(f_i=\max_\limits{1\le j<i} g_j+(i-j)\)

观察上面的式子,不难发现只要以\(pfx_j\)为下标,\(g_j-j\)为权值把所有以及操作过的点都扔到树状数组上,然后查询就是一个前缀最小值

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<algorithm>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=200005,INF=1e9;
int n,a[N],pfx[N],f[N],g[N],rst[N],cnt,ans;
class Tree_Array
{
	private:
		int bit[N];
	public:
		#define lowbit(x) (x&-x)
		inline void init(void)
		{
			for (RI i=1;i<=cnt;++i) bit[i]=-INF;
		}
		inline int get(RI x,int ret=-INF)
		{
			for (;x;x-=lowbit(x)) ret=max(ret,bit[x]); return ret;
		}
		inline void add(RI x,CI y)
		{
			for (;x<=cnt;x+=lowbit(x)) bit[x]=max(bit[x],y);
		}
		#undef lowbit
}BIT;
signed main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (scanf("%lld",&n),pfx[cnt=1]=0,i=1;i<=n;++i)
	scanf("%lld",&a[i]),pfx[i]=pfx[i-1]+a[i],rst[++cnt]=pfx[i];
	sort(rst+1,rst+cnt+1); cnt=unique(rst+1,rst+cnt+1)-rst-1;
	for (i=0;i<=n;++i) pfx[i]=lower_bound(rst+1,rst+cnt+1,pfx[i])-rst;
	for (BIT.init(),BIT.add(pfx[0],0),i=1;i<=n;++i)
	f[i]=BIT.get(pfx[i])+i,g[i]=max(g[i-1],f[i]),BIT.add(pfx[i],g[i]-i);
	for (i=1;i<=n;++i) ans=max(ans,f[i]);
	return printf("%lld",ans),0;
}

H. Watto and Mechanism

Prob

给定\(n\)个文本串和\(m\)个模式串,对于每个模式串判断是否存在某个文本串,使得这两个串之间恰好相差一个字符

\(n,m\le 3\times 10^5,\sum |s|\le 6\times 10^5,s_i\in{a,b,c}\)

Tutorial

首先一眼把所有文本串Hash后的值扔进一个和长度有关的set里,然后对于每个模式串,枚举每一位然后修改成另一个字符,此时变化后的Hash值很好求

然后光速写完交一发WA on 31,估计被卡Hash了,然后就开始加三Hash,魔改seed……

结果上面也提到了,直接GG,只能说自然溢出真是害人不浅啊(下次还写.jpg)

后面补题的时候实在懒得调参了,直接写了个Trie的做法,其实就是把匹配的地方多加上一维表示是否以及出现过改变的位置即可

复杂度看似爆炸其实就是能跑,好像有大佬说因为字符集大小很小的缘故复杂度上界大概是\(O(n\sqrt n)\)的?不过也跑不满的说,实际跑起来很快

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
const int N=600005;
int n,m,len; char s[N]; bool flag;
class Trie
{
	private:
		int ch[N][3],tot; bool end[N];
	public:
		inline Trie() { tot=1; }
		inline void insert(char *s)
		{
			int len=strlen(s+1),now=1; for (RI i=1;i<=len;++i)
			{
				if (!ch[now][s[i]-'a']) ch[now][s[i]-'a']=++tot;
				now=ch[now][s[i]-'a'];
			}
			end[now]=1;
		}
		inline void DFS(CI now=1,CI pos=1,CI sign=0)
		{
			if (!now) return;
			if (pos>len)
			{
				if (sign&&end[now]) return (void)(flag=1);
				return;
			}
			if (sign) DFS(ch[now][s[pos]-'a'],pos+1,sign); else
			{
				RI i; for (i=0;i<3;++i) if (s[pos]-'a'!=i&&pos==len&&ch[now][i]&&end[ch[now][i]]) flag=1;
				for (i=0;i<3;++i) if (s[pos]-'a'!=i) DFS(ch[now][i],pos+1,1);
				DFS(ch[now][s[pos]-'a'],pos+1,sign);
			}
		}
}T;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%s",s+1),T.insert(s);
	for (i=1;i<=m;++i) scanf("%s",s+1),len=strlen(s+1),flag=0,T.DFS(),puts(flag?"YES":"NO");
	return 0;
}

Postscript

今天加大班,晚上马上还有三小时的CF,压力拉满了属于是

标签:02,Summer,Training,le,const,10,int,include,define
From: https://www.cnblogs.com/cjjsb/p/17546092.html

相关文章

  • [VLDBJ 2022]Privacy and efficiency guaranteed social subgraph matching
    Privacyandefficiencyguaranteedsocialsubgraphmatching动机目标是在不影响查询处理的同时保护隐私其中的子图匹配算法PGP查询会先被分解为星形结构(11行),拿这些分解得到的子图去做匹配实验数据集三个N分别表示类型、属性和标签数量。待补充......
  • 20230711巴蜀暑期集训测试总结
    T1考场上咋都理不清楚,太钻牛角尖了。先或再除和先除再或是一样的,相当于要构造一个序列\(d\),使\(\sum\frac1{2^{d_i}}\ge1\)。求\(\lfloor\frac{a_i}{2^{d_1}}\rfloor|\lfloor\frac{a_i}{2^{d_2}}\rfloor|\dots|\lfloor\frac{a_i}{2^{d_n}}\rfloor\)的最小值。考虑从高位到......
  • 2023上半年Android高频面试题汇总(大厂真题+答案解析)
    前言小伙伴们大家好哇,不知道你们在找工作的时候是不是在力扣、在牛客网狂刷真题!可是有时候刷题的数量连起来可以绕地球三圈,但是面试却过不了第三轮!有没有一种可能就是你没有把握住重点!想想我们之前考试是不是老师划了重点,给了往期真题你考得分数高?题海战术是保底策略,能保证你大概率......
  • 每日总结2023年7月11日
    今日学习:DHCP协议:1.客户机/服务器模型2.租约默认为8天3.当租约过半时,客户机需要向服务器申请续租4.当租约超过87.5%时,如果仍然没有和当初提供IP的DHCP服务器联系上,则开始联系其他的DHCP服务器5.固定分配、动态分配、自动分配6. 169.254.X.X和0.0.0.0两个特殊地址,一旦分配到......
  • 2023.7.11
    1//2023.7.11周二2//for循环3publicclasstest4{5publicstaticvoidmain(String[]args)6{7//打印九九乘法表8for(inti=1;i<=9;i++)9{10for(intj=1;j<=i;j++)11{12......
  • GK2023游记
    不会有人高考之后二十多天才更博客吧。。。(写的很烂,单纯想补个坑)大概就是写一下纯whk的高三生活,是不是流水账无所谓,就算当个记录了高三生活开头就不太平,高三的班主任和高二一样(姑且叫他田吧)/jk,由于我比较开朗??反正就是和同桌说话老是被田发现,又因为我高二的时候基本没和......
  • C/C++2022级C语言课程设计任务书[2023-07-06]
    C/C++2022级C语言课程设计任务书[2023-07-06]2022级C语言课程设计任务书【题目1】学籍管理系统一、设计题目学籍管理系统(用动态结构体数组实现)二、设计内容【题目描述】假设某校学生学籍基本信息主要包括:学号(整型)、姓名(字符数组型)、所在系、班级等,本系统应能对这些......
  • 《Web安全基础》02. 信息收集
    目录1:CDN绕过1.1:判断是否有CDN服务1.2:常见绕过方法1.3:相关资源2:网站架构3:WAF4:APP及其他资产5:资产监控本系列侧重方法论,各工具只是实现目标的载体。命令与工具只做简单介绍,其使用另见《安全工具录》。1:CDN绕过CDN(ContentDeliveryNetwork,内容分发网络)是构建在现有网络......
  • 【软考备战·希赛网每日一练】2023年4月24日
    题目及解析来源:2023年04月24日软件设计师每日一练一、今日成绩二、错题总结第一题解析:第二题解析:DPI表示每英寸像素点的个数。300DPI表示每英寸有300个像素点,3×4英寸的图像,像素点数为3×300×4×300=900×1200。第三题解析:机房安全属于物理安全,入侵检测属于网络安全,漏洞补丁......
  • 在WinServer 2022 Core 上安装SCVMM2022和SqlServer2022
    在WindowsServer2022Core上安装SystemCenterVirtualMachineManager(VMM)2022管理服务器和SqlServer2022CU5系统环境如下:OS:windowsserver2022CoreDataCenterDB:SqlServer2022withCU5ADK: Windows11版本22H2的ADK: https://learn.microsoft.com/zh-cn/wi......