ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

"蔚来杯"2022牛客暑期多校训练营1

2022-07-21 02:32:15  阅读:146  来源: 互联网

标签:int 蔚来 LL 多校 long 牛客 while IL define


链接

\(A : Villages: Landlines\)

做法一:将有交集的两个区间合并(显然若一个区间被覆盖可只建电塔使另一个区间被覆盖),两两相邻区间的最短距离的和即为最小值。
做法二:按发电站的位置向左右遍历,对于左边,按建筑区间的最右端位置排序,记录目前电力能到达的最左端,贪心更新,对于右边同理。注意,对左边,可能出现右边边建筑的范围过大使得左端点比发电站区间左端点还左的情况,所以要提前处理左端点的最小值,右边同理。
做法二:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const LL N=4e5+3;
struct hh{
	LL x,r;
	bool operator<(const hh &a) const{
	return x<a.x;}
}a[N];
LL n,pos,R,ans;
bool cmp1(hh &a,hh &b){
	return a.x+a.r>b.x+b.r;
}
bool cmp2(hh &a,hh &b){
	return a.x-a.r<b.x-b.r;
}
IL LL in(){
  char c;LL f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  LL x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
int main()
{
	n=in();
	pos=in(),R=in();
	for(LL i=1;i<n;++i) a[i]=(hh){in(),in()};
	sort(a+1,a+n);
	LL pp=lower_bound(a+1,a+n,(hh){pos,0})-a;
	sort(a+1,a+pp,cmp1),sort(a+pp,a+n,cmp2);
	LL l=1,r=pp,p1=pos-R,p2=pos+R;
	while(l<pp&&a[l].x+a[l].r>=p1) p1=min(p1,a[l].x-a[l].r),p2=max(p2,a[l].x+a[l].r),++l;
	while(r<n&&a[r].x-a[r].r<=p2) p1=min(p1,a[r].x-a[r].r),p2=max(p2,a[r].x+a[r].r),++r;
	for(;l<pp;++l){
		if(p1-a[l].x>a[l].r) ans+=p1-a[l].x-a[l].r;
		p1=min(p1,a[l].x-a[l].r);
	}
	for(;r<n;++r){
		if(a[r].x-a[r].r>p2) ans+=a[r].x-a[r].r-p2;
		p2=max(p2,a[r].x+a[r].r);
	}
	cout<<ans<<endl;
	return 0;
}

\(C :Grab the Seat!\)

将 \((0,1) , (0,m)\) 与坐人位置 \((x,y)\) 连线,\((x,y)\) 右边两线中间的区域就是被挡住的,且被挡住的必然是靠右的连续一段的座位。

发现两个点对彼此没啥影响,可以对两个点分开讨论,取未被遮挡座位的最小值。

考虑 \((0,1)\) ,按座位 \(y\) 坐标从小到大枚举,若某一点与 \((0,1)\) 连线的斜率小于前面行某点的斜率,则这条线会一直被前面的先覆盖,故我们只需维护斜率最大值计算即可。

具体实现时,由于萌新被浮点数整破防了,故用叉积判断斜率大小,为方便,可以在每一行最右端加一个坐人的座位。

#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define LF double
using namespace std;
const int N=1e6+3;
const LF eps=1e-6;

struct poi{
	LL x,y;
	poi operator-(const poi a) const{
	return (poi){x-a.x,y-a.y};}
	
	LL operator*(const poi a) const{
	return x*a.y-y*a.x;}
};
struct hh{
	LL id,x,y;
	poi operator-(const poi a) const{
	return (poi){x-a.x,y-a.y};}
}a[N];
bool cmp1(hh &a,hh &b){
	return a.y<b.y;
}
int n,m,k,q,de[N],bo[N],re[N];
LL Min[N];
IL LL in(){
  char c;LL f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  LL x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
void calc(int Max){
	for(int i=1;i<=m;++i) Min[i]=n+1;
	for(int i=1;i<=Max;++i) if(bo[a[i].id]) Min[a[i].y]=min(Min[a[i].y],a[i].x);
	poi lp=(poi){1,-1},s1=(poi){0,1},s2=(poi){0,m};
	int flag=0;
	for(int i=1,j=0;i<=m;++i){
		LL mi=n+1;
		while(j<Max&&a[j+1].y<=i){
			++j;
			if(bo[a[j].id]) mi=min(mi,a[j].x);
		}
		poi x=(poi){mi,i-1};
		if(lp*x>0) lp=x;
		else Min[i]=min(Min[i],(1ll*(i-1)*lp.x-1)/lp.y+1);
	}
	lp=(poi){1,1};
	for(int i=m,j=Max+1;i;--i){
		LL mi=n+1;
		while(j>1&&a[j-1].y>=i){
			--j;
			if(bo[a[j].id]) mi=min(mi,a[j].x);
		}
		poi x=(poi){mi,i-m};
		if(lp*x<0) lp=x;
		else Min[i]=min(Min[i],(1ll*(m-i)*lp.x-1)/(-lp.y)+1);
	}
	LL ans=0;
	for(int i=1;i<=m;++i) ans+=Min[i]-1;
	printf("%lld\n",ans);
}
int main()
{
	n=in(),m=in(),k=in(),q=in();
	for(int i=1;i<=k;++i) a[i]=(hh){i,in(),in()},bo[i]=1;
	int cnt=k;
	for(int i=1;i<=q;++i){
		de[i]=in();
		a[++cnt]=(hh){i+k,in(),in()};
	}
	sort(a+1,a+cnt+1,cmp1);
	for(int i=1;i<=cnt;++i) re[a[i].id]=i;
	for(int i=1;i<=q;++i) a[re[de[i]]].id=0,a[re[k+i]].id=de[i],re[de[i]]=re[k+i],calc(cnt);
	return 0;
}

\(D : Mocha and Railgun\)

数学题,画个图列个式子就可以得出当直线 \(AB\) 与直线 \(MQ\) 重合时弧长最大。

#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define LF long double
using namespace std;
const LF pi=acos(-1.0);
LF x,y,r,d;   
IL LL in(){
  char c;LL f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  LL x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
int main()
{
	int t=in();
	while(t--){
		r=in(),x=in(),y=in(),d=in();
		LF dis=sqrt(1.0*x*x+1.0*y*y);
		LF th1=acos((dis-d)/r),th2=acos((dis+d)/r);
		printf("%.12LF\n",(th1-th2)*r);
	}
	return 0;
}

\(G : Lexicographical Maximum\)

设位数为 \(len\) ,直觉告诉我们 \(len-1\) 个 \(9\) 很有可能成为答案,除非 \(n\) 的前 \(len-1\) 也为 \(9\) ,此时答案为 \(n\)。

#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define LF long double
using namespace std;
const int N=1e6+3;
char s[N];
IL LL in(){
  char c;LL f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  LL x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
int main()
{
	scanf("%s",s+1);
	int n=strlen(s+1),flag=1;
	for(int i=1;i<n;++i)
	  if(s[i]!='9') flag=0;
	if(flag) printf("%s",s+1);
	else{
		for(int i=1;i<n;++i)
		  printf("9");
	}
	return 0;
}

\(H : Fly\)

按位分析,对于某一个二进制位,值只可能是 \(0,1\) ,对应不取或取。
看到背包问题可以往多项式方向想,分治 \(FFT\) 求出背包方案数,对于 \(b_i,c_i\) 的限制可以逆向消除背物品。
从第 \(0\) 位到第 \(i\) 位,选择物品总价值为为 \(V\),考虑 \(V/2^i\) 与 \(V \mod 2^i\),前者可以向更高位转移,后者与 \(M \mod 2^i\) 的比较可得出 \(V/2^i = M/2^i\) 时 \(V\) 与 \(M\) 的大小关系。
设计状态 \(f_{i,j,k}\) 表示 到第 \(i\) 位,\(j=V \mod 2^i\) 且 \(k=V/2^i\) 时的方案数,设 \(M\) 最高位是 \(m\),
则 \(f_{m+1,0,0}\) 为答案。
求 \(f_i\) ,可用 \(f_{i-1}\) 与该层的背包方案数多项式卷积求得,感觉题解的做法不太好直接卷积,就先将第 \(i-1\) 层的数组转化成 \(i\) 层再卷积(也许是这个的锅?)\(f_{i-1.k,j} -> f_{i,pd(j \& 1,m_{i-1},k),j>>1}\),\(m_{i}\) 为 \(M\) 第 \(i\) 位的数值,\(pd(x,y,z)=x>y || (x==y \& z)\),即对大小进行讨论。

只有80分,留个坑以后有时间(有心情)再调吧。

#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=32e4+15,p=998244353,G=3,Gi=332748118;
int n,k,mm,len,M[70],a[N],b[N],c[N],d[N],_a[N],_b[N],_c[N],_d[N],r[N];
LL m;
int *f[N],g[N],h[2][80004],F[70][2][80004],w[N],Len[N];
vector<int>lim[70];
IL LL in(){
	char c;int f=1;
	while((c=getchar())<'0'||c>'9')
	  if(c=='-') f=-1;
	LL x=c-'0';
	while((c=getchar())>='0'&&c<='9')
	  x=x*10+c-'0';
	return x*f;
}
IL int mod(int x){return x>=p?x-p:x;}
IL int ksm(int a,int b){
	int c=1;
	while(b){
		if(b&1) c=1ll*c*a%p;
		a=1ll*a*a%p,b>>=1;
	}
	return c;
}
IL void calc(int lim){
	for(int i=0;i<lim;++i)
	  r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
IL void NTT(int *a,int lim,int op){
	calc(lim);
	for(int i=0;i<lim;++i)
	  if(i<r[i]) swap(a[i],a[r[i]]);
	for(int i=1;i<lim;i<<=1){
		int wn=ksm(~op?G:Gi,(p-1)/(i<<1));
		for(int j=0;j<lim;j+=i<<1){
			int w=1;
			for(int k=0;k<i;++k,w=1ll*w*wn%p){
				int x=a[j+k],y=1ll*w*a[j+i+k]%p;
				a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
			}
		}
	}
	if(op==-1){
		int inv=ksm(lim,p-2);
		for(int i=0;i<lim;++i) a[i]=1ll*a[i]*inv%p;
	}
}
IL void mul(int *a,int *b,int *c,int n,int m){
	int lim=1;
	while(lim<n+m-1) lim<<=1;
	memcpy(_a,a,4*n),memcpy(_b,b,4*m),
	memset(_a+n,0,4*(lim-n)),memset(_b+m,0,4*(lim-m));
	NTT(_a,lim,1),NTT(_b,lim,1);
	for(int i=0;i<lim;++i) _c[i]=1ll*_a[i]*_b[i]%p;
	NTT(_c,lim,-1);
	for(int i=0;i<n+m-1;++i) c[i]=_c[i];
}
int fenzhi(int k,int l,int r){
	if(l==r){
		f[k]=new int [a[l]+1];
		memset(f[k],0,4*a[l]+4);
		f[k][0]=f[k][a[l]]=1;
		return a[l]+1;
	}
	int mid=l+r>>1,l1=0,l2=0;
	l1=fenzhi(k<<1,l,mid);
	l2=fenzhi(k<<1|1,mid+1,r);
	f[k]=new int [l1+l2-1];
	mul(f[k<<1],f[k<<1|1],f[k],l1,l2);
	return l1+l2-1;
}
IL int pd(int x,int y,int z){return (x>y)||(x==y&&z);}
int main()
{
	int x,y;
	n=in(),m=in(),k=in();
	for(int i=1;i<=n;++i) len+=(a[i]=in());
	fenzhi(1,1,n);
	for(LL i=0,j=1;;++i,j<<=1)
	  if(j&m) M[i]=1;
	  else if(j>m){mm=i;break;}
	for(int i=1;i<=k;++i) x=in(),y=in(),lim[y].push_back(a[x]);
	for(int i=0;i<=len;++i) g[i]=f[1][i];
	for(int j=0,ll=len;j<lim[0].size();ll-=lim[0][j],++j)
		for(int k=lim[0][j];k<=ll;++k)
		    g[k]=mod(g[k]-g[k-lim[0][j]]+p);
	for(int i=0;i<=len;++i) F[0][0][i]=g[i];
	Len[0]=len;
	for(int i=1;i<=mm;++i) Len[i]=(Len[i-1]>>1)+len;
	for(int i=1;i<=mm;++i){
		memset(g,0,sizeof(g));
		for(int j=0;j<=len;++j) g[j]=f[1][j];
		int ll=len;
		for(int j=0;j<lim[i].size();ll-=lim[i][j],++j)
		  for(int k=lim[i][j];k<=ll;++k)
		    g[k]=mod(g[k]-g[k-lim[i][j]]+p);
		memset(h,0,sizeof(h));
		for(int j=0;j<=Len[i-1];++j)
		  for(int k=0;k<=1;++k)
		    h[pd(j&1,M[i-1],k)][j>>1]=mod(h[pd(j&1,M[i-1],k)][j>>1]+F[i-1][k][j]);
		memset(w,0,sizeof(w));
		mul(h[0],g,w,(Len[i-1]>>1)+1,len+1);
		for(int j=0;j<=Len[i];++j) F[i][0][j]=w[j];
		memset(w,0,sizeof(w));
		mul(h[1],g,w,(Len[i-1]>>1)+1,len+1);
		for(int j=0;j<=Len[i];++j) F[i][1][j]=w[j];
	}
	printf("%d\n",F[mm][0][0]);
	return 0;
}

\(I : Chiitoitsu\)

最优策略是摸到一张牌,构成对子就随便打一单张出去,没有就扔掉。
故牌堆中有两种牌,一种是与手上单牌相同的牌,且牌堆里必然有三张相同的,另一种是摸到直接扔的牌。
令 \(f_{j,i}\) 为当手上有 \(j\) 个对子, 牌堆还剩 \(i\) 张牌时的期望步数。我们可以根据对子数量求出单牌数量,进而求出牌堆里两种牌的数量。
转移方程:
\((f_{j,i}+1)*(45-6j)/{(i+1)} -> f_{j-1,i+1}\)
$ (f_{j,i}+1)*(i+6j-35)/(i+1) -> f_{j,i+1},j\not= 7$

#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=36,M=1e5+3,p=1e9+7;
int n,m,t[128],f[8][150],b[8][150],inv[150],bo[150];
char s[N];
IL LL in(){
  char c;LL f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  LL x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
IL int mod(int x){return x>=p?x-p:x;}
IL int ksm(int a,int b){
	int c=1;
	while(b){
		if(b&1) c=1ll*c*a%p;
		a=1ll*a*a%p,b>>=1;
	}
	return c;
}
IL int turn(char c2,char c1){
	return t[c1]*9+c2-'0';
}
int main()
{
	t['p']=1,t['s']=2,t['z']=3;
	n=in();
	for(int i=1;i<=136;++i) inv[i]=ksm(i,p-2);
	for(int i=0;i<=136;++i) f[7][i]=0,b[7][i]=1;
	for(int i=2;i<=122;++i)
	  for(int j=0;j<=7;++j)
	    if(b[j][i]){
	    	int x=13-2*j,s=3*x;
	    	if(i<s) break;
	    	if(j==7){
	    		if(i+1>=3) f[j-1][i+1]=mod(f[j-1][i+1]+1ll*(f[j][i]+1)*inv[i+1]%p*3%p),b[j-1][i+1]=1;
			}
	    	else{
		    	if(j&&i+1>=s+6) f[j-1][i+1]=mod(f[j-1][i+1]+1ll*(f[j][i]+1)*inv[i+1]%p*(s+6)%p),b[j-1][i+1]=1;
				f[j][i+1]=mod(f[j][i+1]+1ll*(f[j][i]+1)*inv[i+1]%p*(i+1-s)%p),b[j][i+1]=1;
	    	}	
	    }
	for(int i=1;i<=n;++i){
		scanf("%s",s+1);
		memset(bo,0,sizeof(bo));
		int x=0;
		for(int j=1;j<=26;j+=2)
		  ++bo[turn(s[j],s[j+1])];
		for(int j=1;j<=34;++j)
		  if(bo[j]==2) ++x;
		printf("Case #%d: %d\n",i,f[x][123]); 
	}
	return 0;
}

\(J : Serval and Essay\)

将 \(x\) 作为基础并以此推导出的结论集合为 \(S_x\)。
结论:若 \(S_x\) 与 \(S_y\) 交集不为空,则一者为另一者的子集。
意会一下还是挺明显的吧(
于是我们可以维护 \(S\) 的集合,将边合并,若 \(S_y\) 只有 \(S_x\) 的入边,说明选了 \(S_x\) 就可以证明 \(S_y\)。
用 \(set\) 维护集合的出边,进行启发式合并,合并边直接将对应点入度减 \(1\) 即可。
最后每个集合的元素数最大值就是答案。

#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=2e5+3;
struct hh{
	int x,y;
};
int n,fa[N],siz[N],deg[N];
set<int>st[N];
set<int>::iterator it1,it2;
queue<hh>q;
IL int in(){
  char c;int f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  int x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
int find(int x){return x==fa[x]?x:find(fa[x]);}
IL void merge(int x,int y){
	if(x==y) return;
	if(st[x].size()<st[y].size()) swap(x,y);
	fa[y]=x,siz[x]+=siz[y];
	while(st[y].size()){
		it1=st[x].lower_bound(*st[y].begin());
		if(it1!=st[x].end()&&*st[y].begin()==*it1){
			if(--deg[*it1]==1) q.push({x,*it1});
		}
		else st[x].insert(*st[y].begin());
		st[y].erase(st[y].begin());
	}
}
void solve(int id){
	n=in();
	for(int i=1;i<=n;++i) st[i].clear(),fa[i]=i,siz[i]=1;
	for(int i=1;i<=n;++i){
		deg[i]=in();int x;
		for(int j=1;j<=deg[i];++j)
		  st[x=in()].insert(i);
		if(deg[i]==1) q.push({x,i});
	}
	while(q.size()){
		hh u=q.front();q.pop();
		merge(find(u.x),find(u.y));
	}
	int ans=0;
	for(int i=1;i<=n;++i) ans=max(ans,siz[find(i)]);
	printf("Case #%d: %d\n",id,ans);
}
int main()
{
	int t=in();
	for(int i=1;i<=t;++i) solve(i);
	return 0;
}

标签:int,蔚来,LL,多校,long,牛客,while,IL,define
来源: https://www.cnblogs.com/yiqiAtiya/p/16500509.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有