首页 > 其他分享 >CSP-S 模拟赛 35

CSP-S 模拟赛 35

时间:2024-10-07 13:12:03浏览次数:8  
标签:mathit int 35 edge MAXN buf CSP 模拟 las

CSP-S 模拟赛 35

rnk14,\(45+45+15+18=123\)。

T1 送花

愚蠢题。看到区间想到线段树,预处理出每个位置的颜色上一次出现的位置,记为 \(\mathit{las}_i\)。从左到右扫右端点,给 \([\max(1,\mathit{las}_{\mathit{las}_i}),\mathit{las}_i]\) 减去 \(d(c_i)\),给 \((\mathit{las}_i,i]\) 加上 \(d(c_i)\)。最后用全局最大值更新答案。搓一个区间加、维护全局最大值的线段树就可解决。

#include<bits/stdc++.h>
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
#define lp p<<1
#define rp p<<1|1
#define mid ((s+t)>>1)
using namespace std;

char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
int read(){
	int x=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x;
}
template<typename T>
void write(T x,char sf='\n'){
	if(x<0)putchar('-'),x=~x+1;
	int top=0;
	do str[top++]=x%10,x/=10;while(x);
	while(top)putchar(str[--top]+48);
	if(sf^'#')putchar(sf);
}
using ll=long long;
constexpr int MAXN=1e6+5;
int n,m,c[MAXN],d[8005];
ll ans=LONG_LONG_MIN;
vector<int>v[8005];
int las[MAXN];
struct SegTree{
	ll c,lazy;
}st[MAXN<<2];
void pushdown(int p){
	if(!st[p].lazy)return;
	st[lp].c+=st[p].lazy;
	st[lp].lazy+=st[p].lazy;
	st[rp].c+=st[p].lazy;
	st[rp].lazy+=st[p].lazy;
	st[p].lazy=0;
}
void mdf(int l,int r,ll k,int s=1,int t=n,int p=1){
	if(l<=s&&t<=r)return st[p].c+=k,st[p].lazy+=k,void();
	pushdown(p);
	if(l<=mid)mdf(l,r,k,s,mid,lp);
	if(mid<r)mdf(l,r,k,mid+1,t,rp);
	st[p].c=max(st[lp].c,st[rp].c);
}

int main(){
	freopen("flower.in","r",stdin);
	freopen("flower.out","w",stdout);
	n=read(),m=read();
	for(int i=1;i<=n;++i)c[i]=read();
	for(int i=1;i<=m;++i)d[i]=read();
	for(int i=1;i<=n;++i)v[c[i]].emplace_back(i);
	for(int i=1;i<=m;++i)
		for(int j=1;j<(int)v[i].size();++j)
			las[v[i][j]]=v[i][j-1];
	for(int i=1;i<=n;++i){
		if(las[i])mdf(max(1,las[las[i]]),las[i],-d[c[i]]);
		mdf(las[i]+1,i,d[c[i]]);
		ans=max(ans,st[1].c);
	}
	return write(ans),fw,0;
}

T2 星空

新鲜的计算几何题。(?

题目给定的这个 “直接距离” 特别的 bug,发现这样一来,所有位于直线 \((\forall b)~y=\pm x+b\) 的点的直接距离都是一样的。考虑将坐标轴逆时针旋转 45 度,这样原来的坐标 \((x,y)\) 会变成 \((x-y,x+y)\),且所有横/纵坐标相等的点的直接距离都相等。

处理出距离为零的那些点用并查集合并,然后将点分别按照 \(x,y\) 排序并找到最近点对,这就是第一问的答案。对于第二问,将所有的最近点加到一个数组中去重,最后就是其中任两者的并查集连通块大小乘积。

#include<bits/stdc++.h>
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
using namespace std;

char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch))ch=='-'&&(f=-1),ch=getchar();
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*f;
}
template<typename T>
void write(T x,char sf='\n'){
	if(x<0)putchar('-'),x=~x+1;
	int top=0;
	do str[top++]=x%10,x/=10;while(x);
	while(top)putchar(str[--top]+48);
	if(sf^'#')putchar(sf);
}
constexpr int MAXN=1e5+5;
int n;
struct Star{
	int x,y,id;
}a[MAXN];
int f[MAXN],siz[MAXN];
int find(int x){
	if(f[x]^x)f[x]=find(f[x]);
	return f[x];
}
void combine(int x,int y){
	int fx=find(x),fy=find(y);
	if(fx==fy)return;
	if(siz[fx]<siz[fy])swap(fx,fy);
	f[fy]=fx;
	siz[fx]+=siz[fy];
}
vector<pair<int,int>>edge;

int main(){
	freopen("sky.in","r",stdin);
	freopen("sky.out","w",stdout);
	n=read();
	for(int i=1,xx,yy;i<=n;++i){
		xx=read(),yy=read();
		a[i]={xx-yy,xx+yy,i};
		f[i]=i,siz[i]=1;
	}
	sort(a+1,a+n+1,[&](Star x,Star y){
		return x.x^y.x?x.x<y.x:x.y<y.y;
	});
	int ans=INT_MAX,ans2=0;
	for(int i=1,j;i<=n;++i){
		j=i+1;
		while(j<=n&&(a[i].x==a[j].x||a[i].y==a[j].y)){
			combine(a[i].id,a[j].id);
			++j;
		}
		if(j<=n)ans=min(ans,a[j].x-a[i].x);
	}
	sort(a+1,a+n+1,[&](Star x,Star y){
		return x.y^y.y?x.y<y.y:x.x<y.x;
	});
	for(int i=1,j;i<=n;++i){
		j=i+1;
		while(j<=n&&(a[i].x==a[j].x||a[i].y==a[j].y)){
			combine(a[i].id,a[j].id);
			++j;
		}
		if(j<=n)ans=min(ans,a[j].y-a[i].y);
	}
	for(int i=1,j;i<=n;++i){
		j=i+1;
		while(j<=n&&(a[i].x==a[j].x||a[i].y==a[j].y))++j;
		if(j<=n&&a[j].y-a[i].y==ans){
			int fx=find(a[i].id),fy=find(a[j].id);
			if(fx>fy)swap(fx,fy);
			edge.emplace_back(fx,fy);
		}
	}
	sort(a+1,a+n+1,[&](Star x,Star y){
		return x.x^y.x?x.x<y.x:x.y<y.y;
	});
	for(int i=1,j;i<=n;++i){
		j=i+1;
		while(j<=n&&(a[i].x==a[j].x||a[i].y==a[j].y))++j;
		if(j<=n&&a[j].x-a[i].x==ans){
			int fx=find(a[i].id),fy=find(a[j].id);
			if(fx>fy)swap(fx,fy);
			edge.emplace_back(fx,fy);
		}
	}
	sort(edge.begin(),edge.end());
	edge.erase(unique(edge.begin(),edge.end()),edge.end());
	for(auto v:edge)ans2+=siz[v.first]*siz[v.second];
	write(ans),write(ans2);
	return fw,0;
}

T3 零一串

双端队列维护 \(0\) 和 \(1\) 的位置。

对于每一个 \(1\) 处理一个长度为 \(T\) 的零一串,每一个 \(1\) 代表这个时刻能不能左移。

考虑如果第 \(i\) 个 \(1\) 可以在 \(j\) 的时刻左移,如果第 \(i+1\) 个位置是紧邻的,那么它只能在 \(j+1\) 的时刻左移。反之如果不紧邻,则后面有几个 \(0\) 可以移几次。神秘差分维护。

#include<bits/stdc++.h>
#define int long long
using namespace std;

constexpr int MAXN=5e6+5,MOD=998244353;
int T,n,pw[MAXN]={1};
string s;
int pos[MAXN],tot;
int cf[MAXN],dis[MAXN],sum[MAXN],ans[MAXN],ans2;
void add(int&x,int y){
	x=x+y>=MOD?x+y-MOD:x+y;
}

signed main(){
	freopen("chuan.in","r",stdin);
	freopen("chuan.out","w",stdout);
	cin>>T>>s;
	for(int i=1;i<=T;++i)pw[i]=pw[i-1]*233%MOD;
	n=s.size();
	s=' '+s;
	for(int i=1;i<=n;++i)if(s[i]=='1')pos[++tot]=i;
	deque<int>q(T);
	iota(q.begin(),q.end(),1);
	for(int i=1,all=0;i<=tot;++i){
		++all;
		if(!q.empty()&&q.back()+all>T)q.pop_back();
		q.emplace_front(1-all);
		for(int j=1;!q.empty()&&j<=pos[i]-pos[i-1]-1;++j){
			++cf[q.front()+all];
			--cf[min(tot-i+q.front()+all+1,T+1)];
			q.pop_front();
		}
		dis[i]=T-q.size();
		ans[pos[i]-dis[i]]=1;
	}
	int nxd=0,num=0;
	for(int i=1;i<=n;++i)
		if(s[i]=='1')++num;
		else add(nxd,num);
	ans2=nxd;
	for(int i=1;i<=T;++i){
		sum[i]=(sum[i-1]+cf[i])%MOD;
		add(nxd,sum[i]);
		ans2^=pw[i]*nxd%MOD;
	}
	for(int i=1;i<=n;++i)cout<<ans[i];
	cout<<'\n'<<ans2<<'\n';
	return 0;
}

T4 Revive

唐。

标签:mathit,int,35,edge,MAXN,buf,CSP,模拟,las
From: https://www.cnblogs.com/laoshan-plus/p/18449927

相关文章

  • CSP-S 模拟赛 34
    CSP-S模拟赛34rnk12,\(24+50+20+0=94\)。T1玩游戏有一个痿正解:从\(k\)到\(1\)扫左端点,对于每个左端点扫它最远能到达的右端点。如果在任何一时刻它的右端点位置\(<k\),则断定输出No。否则检查当左端点到\(1\)时右端点能否到\(n\)。注意这里扫右端点的方式,不要每次都......
  • CSP-S 模拟赛 33
    CSP-S模拟赛33rnk19,\(30+20+40+15=105\)。T1构造字符串10pts:输出\(-1\)。30pts:对于所有\(z_i=0\)的情况,也就是说给定的两个位置字符都不同。记录有哪些位置的字符是不同的,然后从\(1\)到\(n\)扫一遍,输出除去不同的字符之外的字典序最小的字符。70pts:暴搜。枚举每个......
  • P3527 MET-Meteors 题解
    Solution单次二分:二分时间,做这个时间前的所有操作,然后线性统计。注意到可以整体二分,直接整体二分是\(O(n\log^2n)\)。考虑扫描序列,用线段树维护每个时间段内该位置的增加值,差分一下可以实现。将这棵线段树持久化一下,一个国家所有位置同时二分即可\(O(n\logn)\),可惜空间太......
  • 10.5牛客CSP-S考试总结
    10.5牛客CSP-S考试总结为什么牛客不允许我:main(){}T1看到题目感觉是道规律题,就把题目给的式子写出来,跑了几十组随机数据,发现好像是恒等式,于是直接大胆猜测任选三个数都可以满足等式。T2题面数学公式有点诈骗,求自然常数的多个自然对数相加的和的次方,形式化的求\(e^{\ln\......
  • Rockchip RK3588 - Rockchip Linux Recovery recovery源码分析
    ----------------------------------------------------------------------------------------------------------------------------开发板:ArmSoM-Sige7开发板eMMC:64GBLPDDR4:8GB显示屏:15.6英寸HDMI接口显示屏u-boot:2017.09linux:5.10-------------------------------......
  • CSP-S 2024 第九次
    A设\(f_{i,S}\)表示考虑前\(i\)行,选出的矩形在第\(i\)行上形成\(S\)中的区间的方案数,每行的\(S\)只有\(O(2^m)\)种,总复杂度\(O(n2^{2m})\)。B考虑先修改再查询怎么做。考虑左下角为\((x_1,y_1)\),右上角为\((x_2,y_2)\)的矩形,发现斜率在\(\left[\dfrac{y_1}{......
  • 2024-10-6 模拟赛总结
    \(100+80+100+0=280\),暴力又写挂了。比赛链接:http://172.45.35.5/d/HEIGETWO/homework/67025b796735d3863dc7f60d或者http://yl503.yali.edu.cn/d/HEIGETWO/homework/67025b796735d3863dc7f60dA-fountain题意:给定一条线段和一个圆,求线段上任意一点到圆上任意一点的最大距......
  • 多校A层冲刺NOIP2024模拟赛02 & csp-s模拟9
    多校A层冲刺NOIP2024模拟赛02四道题因为暑假被拉去当模拟赛暑假集训CSP提高模拟22了,遂直接把赛后代码交了上去,然后就被通知换题了。原\(100+100+100+20\)被在accodersNOI上被卡成了\(100+100+90+10\),更改longlong和int后达到了\(100+100+100+30\)。\(T1\)P318......
  • CCF-CSP认证资格考试题解系列——第4次第2题数字排序
    #include<iostream>#include<algorithm>usingnamespacestd;structre{ intvalue;//数值 intnum;//次数}re[1010];boolcmp(structrea,structreb){ if(a.num==b.num)returna.value<b.value;//次数相同是小的优先 returna.num>b.num;//次数不相同是次数优......
  • CCF-CSP认证资格考试题解系列——第4次第3题节日
    #include<iostream>usingnamespacestd;intm[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};intis_run(intyear){ if(year%400==0||(year%4==0&&year%100))return1; return0;}intgetdays(intyear,intmonth){ if(month==2)returnm[month]+i......