Loading

noip模拟43

A. 第一题

考场上打的线段树合并\(+\)贪心假了..

贪心应该是正解,但是\(dp\)也可做..

想着线段树合并时间复杂度可以稍微小一点.

于是放弃了每次使用\(set\)维护,但是其实也能过.

结果\(Vector\)暴力扫\(+\)排序维护也能\(A\).

一般的话,如果是二叉树,复杂度为\(O(nlogn)\),但是链的话可以卡成\(O(n)\).

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

const ll N=1e5+51;

ll m,n,ts,ans;
ll head[N],rt[N<<6];
vector<ll> vec[N];
struct I { ll u,v,nxt; } e[N<<1];
inline void add(ll u,ll v){
	e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u];
	head[u]=ts;
}
inline bool comp(ll i,ll j){ return i>j; }
void dfs(ll now,ll dad,ll dep){
	ll flag=1;
	for(re i=head[now];i;i=e[i].nxt){
		if(e[i].v==dad) continue;
		flag=0; dfs(e[i].v,now,dep+1);
		if(vec[now].size()<vec[e[i].v].size()) swap(vec[e[i].v],vec[now]);
		for(auto j : vec[e[i].v]) vec[now].push_back(j);
	}
	if(flag){
		vec[now].push_back(dep); 
		ans+=dep;
		return ;
	}
//	cout<<"Now:"<<now<<" "<<ans<<'\n';
//	for(auto i : vec[now]) cout<<i<<" ";
//	cout<<'\n';
	sort(vec[now].begin(),vec[now].end(),comp);
	if(vec[now].size())
	for(ll i=vec[now].size()-1;i>=1;--i){
		if(vec[now][i]>=2*dep) break;
		ans+=vec[now][i]-2*dep;
		flag++;
	}
	while((flag--) and vec[now].size()){
		vec[now].pop_back();
	}
	return ;
}
signed main(){
	n=read(); ll u,v;
	if(n==1){ cout<<0; return 0; }
	for(re i=2;i<=n;i++) u=read(),v=read(),add(u,v),add(v,u);
	dfs(1,0,0);
	printf("%lld\n",ans);
	return 0;
}

B. 第二题

没有看到单调性,直接挂了.

二分+\(Spfa\)乱跑就行..

每次将所有的点都压入队列,每枚举到一个点,然后就更新周围的六个就可以..

数据依旧过水,这套题的数据我真的没话说了.

复杂度 \(O(\)玄学\()\)

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

const ll N=1e5+51;

ll m,n,t,tot,ts;
ll val[N],head[N],vis[N];
map<pair<ll,ll>,ll> map1;
struct I { ll w; } p[N];
struct II { ll u,v,nxt; } e[N<<6];
inline void add(ll u,ll v){
	e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u],
	head[u]=ts;
}
queue<ll> que;
inline bool Spfa(ll x){
	for(ll i=1;i<=tot;++i){
		val[i]=p[i].w,vis[i]=1;
		que.push(i);
	}
	ll now,res=0;
	while(que.size()){
		now=que.front(); que.pop();
		for(re i=head[now];i;i=e[i].nxt){
			if(val[e[i].v]-val[now]>x){
				res+=val[e[i].v]-x-val[now],val[now]+=val[e[i].v]-x-val[now];
			}
		}
		for(re i=head[now];i;i=e[i].nxt){
			if(val[now]-val[e[i].v]>x){	
				res+=val[now]-x-val[e[i].v],val[e[i].v]+=val[now]-x-val[e[i].v];
				if(!vis[e[i].v]) que.push(e[i].v);
				vis[e[i].v]=1;
			}
		}
		vis[now]=0;
	}
//	cout<<x<<" "<<res<<endl;
	return res<=t;
}
inline void Work(){
	ll l=0,r=1e12,res=r,mid;
	while(l<=r){
		mid=(l+r)>>1;
		if(Spfa(mid)) r=mid-1,res=mid;
		else l=mid+1;
	}
	printf("%lld",res);
	return ;
}
signed main(){
	n=read(),m=read(),t=read(); ll x,y,temp;
	for(ll i=1;i<=n;++i)
		for(ll j=1;j<=m;++j)
			p[++tot].w=read(),map1[mp(i,j)]=tot;
	for(ll i=1;i<=n;++i){
		for(ll j=1;j<=m;++j){
			if(j>1) add(map1[mp(i,j)],map1[mp(i,j-1)]);
			if(j<m) add(map1[mp(i,j)],map1[mp(i,j+1)]);
			if(i>1) add(map1[mp(i,j)],map1[mp(i-1,j)]);
			if(i>1 and j<m) add(map1[mp(i,j)],map1[mp(i-1,j+1)]);
			if(i<n and j>1) add(map1[mp(i,j)],map1[mp(i+1,j-1)]);
			if(i<n) add(map1[mp(i,j)],map1[mp(i+1,j)]);
		}
	}
	Work();
	return 0;
}

C. 第三题

思路来自 \(Yubai\).

\(solve(x)\) 表示求出排名在 \(x\) 以内,值域在 \([L,R]\) 之间的和.

所以答案就是 \(solve(b)-solve(a-1)\).

考虑如何解决 \(solve(x)\).

由于 ta 是按照从大到小排序的,所以我们可以倒序枚举二进制位上 \(1\) 的个数.

考虑求出相应二进制位下值域位于 \([L,R]\) 的数的个数.

然后我们求出前几个二进制位下的总和就可以了.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long 
	#define ull unsigned ll
	#define lf long double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#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)
	inline ll read() {
		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=35;

ll Ts,L,R,ql,qr;
ll f[N][N],g[N][N];
ll dfs1(ll lmt,ll now,ll is){
	if(is>now) return 0; if(!is) return 1; ll res=0;
	if((lmt>>now-1)&1) res+=f[now-1][is],res+=dfs1(lmt,now-1,is-1);
	else res+=dfs1(lmt,now-1,is);
	return res;
}

ll dfs2(ll lmt,ll now,ll is){
	if(is>now) return 0; if(!is) return 0; ll res=0;
	if((lmt>>now-1)&1) res+=g[now-1][is],res+=dfs1(lmt,now-1,is-1)*(1ll<<now-1)+dfs2(lmt,now-1,is-1);
	else res+=dfs2(lmt,now-1,is);
	return res;
}
inline ll solve(ll x){
	ll res=0,fs,gs;
	for(ll i=30;i>=0;i--){
		if(!x) break;
		fs=dfs1(R,30,i)-dfs1(L-1,30,i); //cout<<fs<<' ';
		if(x>=fs) x-=fs,res+=dfs2(R,30,i)-dfs2(L-1,30,i);
		else {
			ll l=L-1,r=R,w,rw=dfs1(R,30,i);
			while(l<=r){
				ll mid=(l+r)>>1;
				if(x>=rw-dfs1(mid,30,i)) r=mid-1,w=mid;
				else l=mid+1;
			}
			res+=dfs2(R,30,i)-dfs2(w,30,i); break;
		}
	}
	return res;
}
signed main(){
	Ts=read();
	for(ll i=0;i<=32;i++){
		f[i][0]=1;
		for(ll j=1;j<=i;j++){
			f[i][j]=f[i-1][j-1]+f[i-1][j];
			g[i][j]=g[i-1][j-1]+g[i-1][j]+(1ll<<i-1)*f[i-1][j-1];
		}
	}
	while(Ts--){
		L=read(),R=read(),ql=read(),qr=read();
		printf("%lld\n",solve(qr)-solve(ql-1));
	}
	return 0;
}

D. 第四题

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

const ll N=3e3+21;

ll n,mod;
ll ans[N];
ll f[N][N],g[N][N],pre1[N][N],pre2[N][N];

signed main(){
	n=read(),mod=read(),f[0][0]=1; ll res;
	for(re i=1;i<=n;i++){
		for(re j=1;j<=i;j++)
			f[i][j]=(f[i-1][j]*j%mod+f[i-1][j-1])%mod;
	}
	for(re i=1;i<=n+1;i++) g[n+1][i]=1;
	for(re i=n;i>=1;i--){
		for(re j=n;j>=1;j--)
			g[i][j]=(g[i+1][j+1]+g[i+1][j]*j%mod)%mod;
	}
	for(re i=1;i<=n;i++){
		for(re j=n;j>=1;j--)
			pre1[i][j]=(pre1[i][j+1]+f[i-1][j]*g[i+1][j]%mod)%mod,
			pre2[i][j]=(pre2[i][j+1]+f[i-1][j]*g[i+2][j]%mod)%mod;
	}
	for(re i=1;i<=n;i++){
		for(re j=1;j<=n;j++){
			res=(pre1[i][j]+(n-i<<1)%mod*pre2[i][j]%mod)%mod,
			(res+=f[i-1][j-1]*(g[i+1][j]+(n-i<<1)%mod*g[i+2][j]%mod)%mod)%=mod;
			ans[j]=(ans[j]+res)%mod;
		}
	}
	for(re i=1;i<=n;i++) printf("%lld ",ans[i]);
	puts(""),exit(0);
}
posted @ 2021-08-19 19:48  AaMuXiiiiii  阅读(69)  评论(0)    收藏  举报