ICode9

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

noip模拟82(待补)

2021-10-22 08:33:13  阅读:160  来源: 互联网

标签:ch noip 待补 res ll mn 82 mx define


A. 魔法

随便写.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define ll int
	#define lf double
	#define ull unsigned ll
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[]()->ll{
		ll w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:(-w);
	};
} using namespace BSS;

const ll N=1e6+21;

char ch[N];

ll A,B;
ll n,as,bs,ab,ans,tail;
ll val[N],pos[N],vis[N],in[N];
ll L[N],R[N];
ll pre[N][3];
struct I { ll w,id; } p[N];
vector<ll> vec[N];
signed main(){
	File(magic);
	n=read(),A=read(),B=read(),ab=A+B; scanf("%s",ch+1);
	for(ll i=1;i<=n;i++){
		val[i]=(ch[i]=='R' ? 1 : 2);
		(val[i]&1) ? as++ : bs++ ;
	}
	if(as*B!=bs*A) puts("NO"),exit(0);
	if((as+bs)%(A+B)) puts("NO"),exit(0);
	if(A and as%A) puts("NO"),exit(0);
	if(B and bs%B) puts("NO"),exit(0);
	as=0,bs=0,tail=0;
	for(ll i=1;i<=n;i++){
		pos[++tail]=i,pre[tail][1]=pre[tail-1][1],pre[tail][2]=pre[tail-1][2];
		(val[i]&1) ? (pre[tail][1]++) : (pre[tail][2]++) ;
		as=pre[tail][1]-pre[max(tail-ab,0)][1];
		bs=pre[tail][2]-pre[max(tail-ab,0)][2];
		if(as==A and bs==B){
			ans++;
			for(ll j=tail-ab+1;j<=tail;j++) vec[ans].push_back(pos[j]),vis[pos[j]]=ans;
			tail-=ab;
		}
	}
	puts("YES");
	printf("%d\n",ans);
	for(ll i=1;i<=n;i++){
		if(!in[vis[i]]){
			for(auto j : vec[vis[i]]) printf("%d ",j);
			in[vis[i]]=1; puts("");
		}
	}
	exit(0);
}

B. 连通性

发现这个题目一开始很难做,因为根本无从下手.

我们考虑一下 \(Floyed\) 算法的实现过程,大概就是有一部分点依靠中间点建立联通关系.

对于一些没有被中间点联通的点对来说,\(AttackedFloyed\) (以下简称 \(AF\))最终跑出来的还是本来就直接联通的点对.

同样设 \(1\) ~ \(n-m\) 的点为黑点,设 \(n-m+1\) ~ \(n\) 的点为白点.

所以我们可以直接发现,对于白点来说,ta 们之间的路径,一定是除了端点之外全部都是黑点.

所以我们就可以来跑 \(dp\) 了,需要用到围绕基准点的思想.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define ll long long int
	#define lf double
	#define ull unsigned ll
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[]()->ll{
		ll w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:(-w);
	};
} using namespace BSS;

const ll N=105,mod=1e9+7;

ll g[N],pow2[N*N];
ll h[N][N],C[N][N],f[N][N];
auto ksm=[](ll a,ll b,ll c)->ll{
	ll w=1; a%=c;
	for(;b;b>>=1,a=a*a%c) if(b&1) w=w*a%c;
	return w%c;
};
auto PreWork=[]()->void{
	for(ll i=0;i<=100;i++){
		C[i][0]=1;
		for(ll j=1;j<=i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
	}
	g[0]=0,pow2[0]=1;
	for(ll i=1;i<=10000;i++) pow2[i]=(pow2[i-1]<<1ll)%mod;
	for(ll i=1;i<=100;i++){
		g[i]=pow2[i*(i-1)>>1];
		for(ll j=1;j<=i-1;j++)
			g[i]=(g[i]-g[j]*pow2[(i-j)*(i-j-1)>>1]%mod*C[i-1][j-1]%mod+mod)%mod;
	}
	for(ll i=0;i<=100;i++){
		for(ll j=0;j<=100;j++){
			h[i][j]=g[j]*ksm(pow2[j]-1,i,mod)%mod*pow2[i*(i-1)>>1]%mod;
		}
	}
	f[1][0]=1,f[0][0]=1,f[1][1]=1;
	for(ll n=2;n<=100;n++){
		f[n][0]=pow2[n*(n-1)>>1];
		for(ll m=1;m<=n;m++){	
			for(ll i=1;i<=m;i++){
				f[n][m]=(f[n][m]+f[n-i][m-i]*C[m-1][i-1]%mod)%mod;
				for(ll j=0;j<=n-m;j++)
					f[n][m]=(f[n][m]+f[n-i-j][m-i]*C[m-1][i-1]%mod*C[n-m][j]%mod*h[i][j]%mod)%mod;
			}
		}
	}
};
signed main(){
	File(floyd);
	PreWork(); ll n,m;
	for(int Ts=read();Ts;Ts--) n=read(),m=read(),printf("%lld\n",f[n][m]);
	exit(0);
}

C. 矩形

首先很自然的就感觉这可能会是个笛卡尔树或者单调栈之类的结构.

我们发现我们如果暴力 \(O(n^2)\) 做的话,空间上也需要存储 \(O(n^2)\) 的数据,于是很难不排除全部存储的想法.

所以考虑排除一些没有用的东西的枚举和储存.

一开始只考虑了对于排名一定大于 \(R\) 的直接不存,也就是维护一个类似于堆的结构,发现还是不行.

观察到 \(R-L+1\le3e5\),发现这个数据范围是可以接受的,于是考虑也去排除排名小于 \(L\) 的.

一开始考虑了权值线段树,发现面积一定是由 \(a*h\) (底乘高) 构成的,发现 \(a\) 的范围只有 \(1~n\),感觉很可做.

想着想着就发现我们在这个算法下面是需要分别找到排名位于 \(L\) 和 \(R\) 的权值.

感觉这个东西就是用来二分做的,如果我们能够迅速找到这个权值,那么接下来的东西就都很好做了.

在这个思路下,很容易发现我们还需要在权值线段树下二分,发现复杂度在 \(O(n*logn*logW)\),于是开始入手.

手玩了一下,发现是个等差数列,线段树直接不需要了,于是复杂度又变成了 \((OlogW)\),从而就很好写了.

关于二分,我们可以选择二分出排名位于 \(L/R\) 的面积,然后枚举每个点,既然我们的面积已定,如果我们枚举每个点,以这个点为最低的点,从而使高确定,那么底的长度所不大于的限制应该也是确定的.

关于等差数列:(以下用 \(1\) 表示根的位置,用 \(0\) 表示左右儿子所在的区间)
\(eg\): \(00001000000000\)
很难不发现,以在这个区间且经过 \(1\) 的一段连续线段为底的矩形的高都是根的 \(h\) (由于是小根堆),且底的长度位于不同的长度也有不同的选择方案.
设 \(1\) 及其较短一侧(例子中为左侧)的长度为 \(mn\),\(1\) 及其较长一侧(例子中为右侧)的长度为 \(mx\),设当前的底的长度为 \(a\).
例子中的 \(mn\) 等于 \(5\),\(mx\) 等于 \(10\).
长度位于 \(mx+1\) ~ \(len\) 的 \(a\),发现最多只能选择 \(len-a+1\) 个,于是等差数列显然.
长度位于 \(mn+1\) ~ \(mx\) 的 \(a\),最多只能选择 \(mn\) 个,枚举左端点显然.
长度位于 \(1\) ~ \(mn\) 的 \(a\),最多只能选 \(a\) 个,同样等差数列显然.

于是我们二分的总复杂度就是 \((OlogW)\),找到了 \(L\) 和 \(R\) 分别位于的权值,那么填数也就很简单了,不再赘述.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define ll long long 
	#define lf double
	#define ull unsigned ll
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[]()->ll{
		ll w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:(-w);
	};
} using namespace BSS;

#define ls (x<<1)
#define rs (x<<1|1)
const ll N=6e5+21,inf=1e15;

ll L,R;
ll m,n,cnt,vall,valr,tail,maxn;
ll bin[N<<1],stk[N];
struct I { ll l,r,w,mn,mx,len; } p[N];
auto calc=[](ll x,ll y)->ll{
	ll mx=p[x].mx,mn=p[x].mn,len=p[x].len,res=0;
	ll z,tmp; y=min(y,len);
	if(y>mx) z=y-mx,y=mx,res+=(mn-1+mn-z)*z/2;
	if(y>mn) z=y-mn,y=mn,res+=mn*z;
	if(y>0) z=y,y=0,res+=z*(z+1)/2;
	return res;
};
auto check=[](ll rkw)->ll{
	ll x,y,z,rks=0;
	for(ll i=1,len;i<=n;i++){
		len=rkw/p[i].w,rks+=calc(i,len);
	}
	return rks;
};
auto getval=[](ll x)->ll{
	ll l=0,r=maxn,mid,res;
	while(l<=r){
		mid=(l+r)>>1;
		if(check(mid)>=x) r=mid-1,res=mid;
		else l=mid+1;
	}
	return res;
};
signed main(){
	File(rectangle);
	n=read(); ll x,y,z,l,r,mn,mx;
	for(ll i=1;i<=n;i++){
		p[i].w=read(),p[i].l=i,p[i].r=i;
		while(tail and p[x=stk[tail]].w>p[i].w){
			p[x].r=i-1,tail--;
			p[i].l=min(p[i].l,p[x].l);
		}
		stk[++tail]=i;
	}
	while(tail) x=stk[tail--],p[x].r=n;
	// for(ll i=1;i<=n;i++) cout<<p[i].l<<' '<<p[i].r<<endl;
	for(ll i=1;i<=n;i++){
		p[i].len=p[i].r-p[i].l+1;
		maxn=max(maxn,p[i].w*p[i].len);
		p[i].mn=min(i-p[i].l+1,p[i].r-i+1);
		p[i].mx=max(i-p[i].l+1,p[i].r-i+1);
	}
	L=read(),R=read(),vall=getval(L),valr=getval(R);
	// printf("%lld\n%lld\n",vall,valr); 
	vall++,valr--;
	for(ll i=1;i<=n;i++){
		l=ceil(1.0*vall/p[i].w),r=min(valr/p[i].w,p[i].len);
		mn=p[i].mn,mx=p[i].mx;
		if(r>mx){
			for(ll j=max(mx+1,l);j<=r;j++){
				for(ll k=1;k<=p[i].len-j+1;k++){
					bin[++cnt]=j*p[i].w; // ~~~
				}
			}
			r=mx;
		}
		if(r<l) continue;
		if(r>mn){
			for(ll j=max(mn+1,l);j<=r;j++){
				for(ll k=1;k<=mn;k++) bin[++cnt]=j*p[i].w;
			}
			r=mn;
		}
		if(r<l) continue;
		if(r>0){
			for(ll j=max(1ll,l);j<=r;j++){
				for(ll k=1;k<=j;k++) bin[++cnt]=j*p[i].w;
			}
		}
	}
	// sort(bin+1,bin+1+cnt);
	// for(ll i=1;i<=cnt;i++) printf("%lld ",bin[i]); 
	// puts("");
	vall--;  
	for(ll i=1,lmt=check(vall)-L+1;i<=lmt;i++) bin[++cnt]=vall;
	for(ll i=1,lmt=R-check(valr);i<=lmt;i++) bin[++cnt]=valr+1;
	sort(bin+1,bin+1+cnt);
	for(ll i=1;i<=R-L+1;i++) printf("%lld ",bin[i]); 
	exit(0);
}

D. 排列

标签:ch,noip,待补,res,ll,mn,82,mx,define
来源: https://www.cnblogs.com/AaMuXiiiiii/p/15437044.html

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

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

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

ICode9版权所有