其他分享
首页 > 其他分享> > 南昌邀请赛 赛后总结与补题

南昌邀请赛 赛后总结与补题

作者:互联网

以下所有代码为自己xjb写的,不确定对不对,如果有重现赛,可以交一交

 

本次邀请赛,说明我们队还是离邀请赛金或者区域赛稳银还是有很大的距离的,

一方面,是暴露出的种种的不足;另一方面,可能需要反思的是平时的学习模式的问题

毕竟在ACM的道路上,还是有种种不利因素,阻止着变强啊

 

热身赛

AD水题,B是大模拟没写出来,

C是一个类似康托展开的魔改,

在允许字母可重的情况下,对字符串s(|s|<=16)全排列之后去重,询问第k大的排列

一开始敲了一发康托展开的板子,打表输出了一些奇奇怪怪不按字典序出牌的东西

后来被归神指出重复排列会被当成两个,卡了会之后想到了枚举这一位填什么字母,增序枚举,

所在的rank区间[L,R],如果[L,R]包含k就填这一位,否则就加上这段rank,再往大里填

然而写了1个小时,回宾馆调了调调过样例了也不知道对不对

当然,写一半的时候,主办方说BC数据出锅了,不然那么多金爷怎么可能做不出来

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool flag;
char ans[20],s[20];
int now[26],len;
ll A[20],p,tmp,rk;
int main()
{
	A[0]=1;
	for(int i=1;i<=16;++i)
	A[i]=A[i-1]*i;
	while(~scanf("%s%lld",s,&p))
	{
		if(s[0]=='#'&&!p)break;
		len=strlen(s);
		memset(now,0,sizeof now);
		rk=1;
		for(int i=0;i<len;++i)
		now[s[i]-'A']++;
		for(int i=1;i<=len;++i)
		{
			flag=0;
			for(int j=0;j<26&&!flag;++j)
			{
				if(!now[j])continue;
				ll all=A[len-i];
				for(int k=0;k<26;++k)
				{
					if(!now[k])continue;
					if(k==j)tmp=A[now[k]-1];
					else tmp=A[now[k]];
					all/=tmp;
				} 
				//printf("char:%c [%lld,%lld]\n",j+'A',rk,rk+all-1); 
				if(rk<=p&&p<=rk+all-1)//[rk,rk+all-1]
				{
					//printf("char:%c rk:%lld all:%lld\n",j+'A',rk,all);
					ans[i]=j+'A';
					now[j]--;
					flag=1; 
				}
				else rk+=all;
			}
		}
		for(int i=1;i<=len;++i)
		putchar(ans[i]);
		puts("");
	}
	return 0;
}

 

正赛

槽,正赛有三份英文题面一份中文题面是什么鬼

L题,直接输出5个数,2min1Y,我也想0min1Y啊,然而找到这个题敲完就2min了

K题,a[i]的前缀和,排个增序,小的对应乘小的,排序不等式和最大,输出这个和,归神单开,7min1y

F题,1e5个数,1e5个询问,两种操作,一个单点改数,另一个询问[L,R],

其每个L<=l<=r<=R的子区间(l,r)的贡献定义为这个子区间所有值的异或,求[L,R]内所有子区间的贡献的异或

涛神率先提出的思路,统计每个值被计了多少次,是(i-l+1)*(r-i+1)次,然后分l和r是否同奇偶讨论,

如果同奇偶,再分i是否和l、r同奇偶讨论,奇数位置开一棵线段树,偶数位置开一棵线段树

归神的线段树写了点小bug,我跟着调出来了,39min1y,

想了想BIT也可以维护区间异或,觉着要是敲着更熟练的话,时间可以更短,赛后试了下的确如此

看了一下榜,J题和G题各有几个队过,我开了J,归神看了G

J是一个裸的字典树,1e5个串,串总长小于2e5,每个小写字母对应一个hash值,

整个串的hash值是所有字母hash值的乘积%m,对于每个串问有多少前缀满足在模意义下,hash值比整个串小,

我约20分钟敲了个板子然而结果不对,归神这时候G有了思路先让他敲G,我只好打印代码debug,

后来发现,先是数组重名了,然后自己令rt=1结果开节点还在tot=0的情况下++tot,写好这里之后90min1y了,

的确是因为自己板子的问题,没能更快的1y,要整理一个好的字典树板子①

G题是一个贪心叭,1e5个人,每个人有三个权值ai,bi,ci,

题目保证ai两两不同,bi,ci同理,只要有一个权值比另一个人的对应权值大,这个人就可以赢另一个,

要举办n-1场比赛,主办方每次可以指定两个未淘汰选手,指定用哪个权值进行比较,

最后1e5个询问,询问每个人是否能成为冠军

首先,三个权值分别最大的人ABC是能成为冠军的,也因此更新了他们在别的领域的最小值,

如果D能战胜这些最小值的一个,就能让那个人先把n-2个人扫了之后,再最后一轮输给D,

所以就是不断更新最小值至不能再更新

归神提了一个按值更新的做法,RE了一发又WA了一发,这个时候我们想听思路,我问涛神涛神也没听懂,

涛神后来懂了帮归神debug,说两个人懂了就没必要再讲了,我就去新开题了,

我在这一个多小时是挂机的,想跟榜但是榜过别的题的人寥寥无几只有两三个,

然而归神心态有点崩,又分别WA和RE了一发,177min5y

看了一下榜,5题罚时404rank81,而且已经有七八十个队伍是五题及以上了,

且如果少一发罚时的话,能前进约10名左右,诶,又是一个罚时局

后两个小时就很无力了,一方面是有中餐之后代码输出力--(麦当劳中餐好评呀,感觉中餐投入得是其它赛区的两倍)

另一方面也是后期题我们知识重合的部分比较少,在配合方面,还有很多不足

我开了H题,涛神开了B题,期间也看过A题、D题和E题,

A题想过用费用流,但不会处理多次通过这条边只记录一次流量,赛后才知道竟然是斯坦纳树裸题……

看完几个题之后,感觉可能能做的也就B和H

涛神看了一会B题发现不会做,我跟着看了一会,提出如果能求\sum_{i=1}^{n}i^{k}就好了,然而仨人都不会求,

而且高斯消元的复杂度O(n^3)在这里解n=1e3的式子很拙计,更何况大家都只是天天口胡并没有套过板子

赛后才知道是裸的拉格朗日差值,而且我收藏夹里有拉格朗日差值,例题就是求这个式子,槽

我看了H题,发现前半部分是裸的FWT抄了一发板子,然而后半部分被我理解错了题意(背锅)

神奇的是,我在做这个题的时候对面电子科大的dove队9发破I之后也在搞这个题,

而且进度近乎和我一致,然而他们最后1h也没能过这个题,估计也是读错题了

是对FWT之后的序列维护两种操作,一种是[l,r]内暴力开根,另一种是询问位置x的值,

我当时以为开根完之后数变小会跑到前面去,赛后看知乎也有中学生和我理解的一样,用的splay,槽

然后我就和归神在那里敲权值线段树,每次暴力开[l,r]区间然后忽视已经值是1的部分,

我自己权值线段树敲被理解错的这题估计也需要2h,归神也坦言说自己可能也需要2h敲,

一方面是第五题导致时间不太够,另一方面也的确是大家的后期输出力可能还有待提升

然而开根之后的数的位置是不变的,于是就变成了二分位置之后一个离散化+线段树区间覆盖的板子题

另一方面,虽然我和归神都能手敲区间覆盖,但感觉这种板子还是要有的,毕竟赛场争分夺秒,不容出错

现在觉得也是最后一个小时大家都不大稳叭,

我那个时候固执地觉得是位置移动的,涛神也直接说自己挂机了,

就感觉仨人的状态都有下降吧,如果能完整地手跑一下样例,应该是能区别出这种情况的

赛后去请教山东理工大学过这个题的队伍解法之后,感觉不读错题的情况下,应该是可以1h调出来的

不过赛后也证明,我们的罚时自第五题之后连交第六题AC也不能金了,所以可能没什么好遗憾的,菜就完事了

5题银到铁,滚榜的时候看那个罚时一会1分钟2分钟的往前减一会掉七八分钟当时觉得很有可能是铜,

结果,rk81最后掉到rk85,算是捡了个银牌倒数叭,诶如果能过第六题,哪有这么多需要担忧的

一方面说明大家的水平可能差不多,另一方面也说明,在做中期题这方面,我们还是不如其他学校

喔,顺便一提,F题和J题好像是数据出锅了,被某些队伍F暴力/J两个map卡过去了

赛后逛知乎发现,I题是一个优雅的暴力的思维题,只是因为没人开;

C题欧拉降幂+dp,可补,但的确也是因为榜上过题人数少,没开

 

从个人方面分析一下自己可能存在的不足吧,有则改之,无则加勉

①思维题训练量不够

在这方面,CF还是利于培养思维,10多场和100多场的区别,高下立判

②赛后不补题的坏习惯

这个就不用多说了,蒟蒻ACMER的通病

③口胡题解之后不注重代码实现

AC is OK,其他都是0

④互膜的不良风气

可能这是高中OIER圈也存在的风气吧,只有自己内心深处,才知道自己多菜吧

⑤过题之后水群炫耀

多过题,少水群,少吹比,很多知识,只有自己不会

⑥刷水题寻找满足感

还是要走出自己的comfort zone叭,Claris也曾说过,只有做自己不会的题才会有提升

⑦学习新知识时死抠原理

这也是自己上学期只学知识不做题的弊病叭,更重要的是应用

⑧学知识时找偏难怪得学

有些知识学了之后八百年也不一定考一次,考的时候可能都不记得自己学过了

区域赛后期题也往往不会出裸题,邀请赛这种是特例 

⑨因为知识名字比较怪望而生畏

犹记得自己嚷嚷着学启发式合并到现在还没有学,拉格朗日插值至今躺在收藏夹里或许也是这个原因吧……

少从队友身上找理由,多从自己身上找不足,你是主代码手呀!

F题

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int tr[2][maxn],a[maxn];
int t,n,m;
int op,l,r;
void add(int *a,int x,int v)
{
	for(int i=x;i<=n;i+=i&-i)
	a[i]^=v; 
}
int Xor(int *a,int x)
{
	int ans=0;
	for(int i=x;i>0;i-=i&-i)
	ans^=a[i];
	return ans;
}
int main()
{
	scanf("%d",&t);
	for(int cas=1;cas<=t;++cas)
	{
		memset(tr,0,sizeof tr);
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;++i)
		{
			scanf("%d",&a[i]);
			if(i&1)add(tr[0],i,a[i]);
			else add(tr[1],i,a[i]);
		}
		printf("Case #%d:\n",cas);
		for(int i=1;i<=m;++i)
		{
			scanf("%d%d%d",&op,&l,&r);
			if(!op)
			{
				if(l&1)add(tr[0],l,a[l]),add(tr[0],l,r);
				else add(tr[1],l,a[l]),add(tr[1],l,r);
				a[l]=r;
				continue;
			}
			if((r-l)&1){puts("0");continue;}
			else
			{
				if(l&1)printf("%d\n",Xor(tr[0],r)^Xor(tr[0],l-1));
				else printf("%d\n",Xor(tr[1],r)^Xor(tr[1],l-1));
			}
		}
	}
	return 0;
}

G题

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
struct node
{
	int v,id;
	node(){}
	node(int vv,int i):v(vv),id(i){
	}
}tmp;
bool operator<(node a,node b)
{
	return a.v<b.v;
}
priority_queue<node>p[3];
int mn[3],a[3][maxn];
int n,q,v;
bool ok[maxn],flag;
int main()
{
	for(int i=0;i<3;++i)
	mn[i]=INF;
	scanf("%d%d",&n,&q);
	for(int j=0;j<3;++j)
	{
		for(int i=1;i<=n;++i)
		{
			scanf("%d",&a[j][i]);
			p[j].push(node(a[j][i],i));
		}
	}
	for(int i=0;i<3;++i)
	{
		tmp=p[i].top();p[i].pop();
		ok[tmp.id]=1;
		mn[i]=min(mn[i],a[i][tmp.id]);
		mn[(i+1)%3]=min(mn[(i+1)%3],a[(i+1)%3][tmp.id]);
		mn[(i+2)%3]=min(mn[(i+2)%3],a[(i+2)%3][tmp.id]);
	}
	flag=1; 
	while(flag)
	{
		flag=0;
		for(int i=0;i<3;++i)
		{
			while(!p[i].empty()&&p[i].top().v>mn[i])
			{
				tmp=p[i].top();p[i].pop();
				if(ok[tmp.id])continue;
				ok[tmp.id]=1;flag=1;//代表本次更新有人被取出 
				mn[(i+1)%3]=min(mn[(i+1)%3],a[(i+1)%3][tmp.id]);
				mn[(i+2)%3]=min(mn[(i+2)%3],a[(i+2)%3][tmp.id]);
			}
		}
	}
	for(int i=1;i<=q;++i)
	{
		scanf("%d",&v);
		puts(ok[v]?"YES":"NO");
	}
	return 0;
} 

H题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+5;
const int maxm=1e5+5;
int n,m;
ll x[maxn],y[maxn];
ll dat[maxn*5],cov[maxn*5];
ll a[maxn],b[maxn],N,mx,v;
ll num[maxn],cnt,tot;
ll in[maxn],cal;
ll sum[maxn];
struct node
{
	ll x,y,id;
	ll tox,toy;
	node(){}
	node(ll xx,ll yy,ll p):x(xx),y(yy),id(p){}
}e[maxm];
void pushup(int p)
{
	dat[p]=dat[p<<1]+dat[p<<1|1];
}
void pushdown(int p,int l,int r)
{
	if(cov[p])
	{
		int mid=l+r>>1;
		cov[p<<1]+=cov[p];
		dat[p<<1]+=cov[p]*(mid-l+1);
		cov[p<<1|1]+=cov[p];
		dat[p<<1|1]+=cov[p]*(r-mid);
		cov[p]=0;
	}
}
void update(int p,int l,int r,int ql,int qr)
{
	if(ql<=l&&r<=qr)
	{
		dat[p]+=r-l+1;
		cov[p]++;
		return;
	}
	pushdown(p,l,r);
	int mid=l+r>>1;
	if(ql<=mid)update(p<<1,l,mid,ql,qr);
	if(qr>mid)update(p<<1|1,mid+1,r,ql,qr);
	pushup(p);
}
int ask(int p,int l,int r,int pos)
{
	if(l==r)return dat[p];
	pushdown(p,l,r);
	int mid=l+r>>1;
	if(pos<=mid)return ask(p<<1,l,mid,pos);
	else return ask(p<<1|1,mid+1,r,pos);
}
void FWT_or(ll *a,int op)
{
	for(int i=1;i<N;i<<=1)
	{
		for(int p=i<<1,j=0;j<N;j+=p)
		{
			for(int k=0;k<i;++k)
			{
				if(op==1)a[i+j+k]=a[j+k]+a[i+j+k];
				else a[i+j+k]=a[i+j+k]-a[j+k];
			}
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;++i)
	{
		scanf("%lld",&v);
		mx=max(mx,2*v);
		a[v]++;
	}
	for(int i=0;i<n;++i)
	{
		scanf("%lld",&v);
		mx=max(mx,2*v);
		b[v]++;
	}
	N=1;
	while(N<mx)N*=2;
	FWT_or(a,1);
	FWT_or(b,1);
	for(int i=0;i<N;++i)
	a[i]=a[i]*b[i];
	FWT_or(a,-1);
	//sum[0]=1;
	for(int i=1;i<=N;++i)
	{
		if(!a[i])continue;
		in[++cal]=i;
		sum[cal]=sum[cal-1]+a[i];
	}
	//for(int i=1;i<=cal;++i)
	//printf("in[%d]:%d sum[%d]:%lld\n",i,in[i],i,sum[i]);
	scanf("%d",&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld%lld",&x[i],&y[i]);
		e[i]=node(x[i],y[i],i);
		if(!x[i])num[++cnt]=y[i];
		else num[++cnt]=x[i],num[++cnt]=y[i];
	}
	sort(num+1,num+cnt+1);
	int tot=unique(num+1,num+cnt+1)-num;
	for(int i=1;i<=m;++i)
	{
		if(!e[i].x)e[i].toy=lower_bound(num+1,num+tot+1,e[i].y)-num;
		else
		{
			e[i].tox=lower_bound(num+1,num+tot+1,e[i].x)-num;
			e[i].toy=lower_bound(num+1,num+tot+1,e[i].y)-num;
		}
	}
	for(int i=1;i<=m;++i)
	{
		if(!e[i].x)
		{
			ll c=in[lower_bound(sum,sum+cal,e[i].y)-sum];
			int res=ask(1,1,tot,e[i].toy);
			if(res>6){puts("1");continue;}
			for(int j=1;j<=res;++j)
			c=sqrt(c);
			printf("%lld\n",c);
		}
		else update(1,1,tot,e[i].tox,e[i].toy);
	}
	return 0;
} 
/*
5
6 2 6 4 5
1 7 9 10 3
5
17 21
0 8
8 13
0 8 
0 20
*/ 

 

标签:int,ll,邀请赛,归神,maxn,补题,id,1e5,赛后
来源: https://blog.csdn.net/Code92007/article/details/90769596