Loading

Noip模拟100 2021.11.17

直接给我整了个原题大战,出题人四处嫖题就非常离谱。。。

我是小马 桶 ,今天终于一百场了我真开心

T1 饥饿的狐狸

比较水的贪心,不知道为啥洛谷上面评级是紫的。。。。

题意可以转化为规定每次走的位置和一个可以随时到达的原点,要求最大化和最小化行走的距离

显然可以先把\(T\)升序排序

先看当\(W=0\)的情况,比较好想出最小值直接就是\(T_n\),最大值可以通过观察你的全排列的暴力得出结论

最大值的时候直接反复横跳就是答案,其实性感理解的话比较好想出,但是我考场上打了暴力我为什么还要想呢??

这样我们继续考虑原点不是\(0\)的情况,发现还是可以用反复横跳来解决,只不过起点需要找到距离原点最远的点

但是我为了保证贪心正确打了好几个不同的贪心取了最大值,里面还有一个随即贪心。。。。1

最小值的话需要找到离原点最近的两个点,然后分别向最小值和最大值的方向移动即可

注意在累计答案的时候都需要和到原点的距离进行比较,因为如果这时候去原点更优肯定会选择先去一下原点(也就是先喝一口水再吃)

a
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace AE86{
	FILE *wsn;
	#define gc() p1==p2 and (p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++
	char buf[1<<20],*p1=buf,*p2=buf;
	auto read=[](){
		int x=0,f=1;char ch=gc();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=gc();} return x*f;
	};
	auto write=[](int x,char opt='\n'){
		char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
		do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
		for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
	};
	#define mzs
}using namespace AE86;
const int NN=1e6+5;
int n,w,t[NN];
auto task=[](int sm=0){
	sort(t+1,t+n+1);int it1=1,it2=n,pre=0;
	for(int i=1;i<=n;i++){
		if(i&1){
			sm+=max(abs(t[it2]-pre),abs(t[it2]-w));
			pre=t[it2--];
		}else{
			sm+=max(abs(t[it1]-pre),abs(t[it1]-w));
			pre=t[it1++];
		}
	}
	printf("%lld %lld\n",t[n],sm);
};
int mx,mn;
bool vis[NN];
auto getnum=[](){
	int x=rand()%n+1;
	while(vis[x]) x=rand()%n+1;
	vis[x]=1; return x;
};
auto greedymax=[](){
	int itl=1,itr=n,pre=w;
	int tmp=0;
	for(int i=1;i<=n;i++){
		if(i&1){
			tmp+=max(abs(t[itl]-pre),abs(t[itl]-w));
			pre=t[itl++];
		}else{
			tmp+=max(abs(t[itr]-pre),abs(t[itr]-w));
			pre=t[itr--];
		}
	}
	mx=tmp; itl=1; itr=n; pre=w; tmp=0;
	for(int i=1;i<=n;i++){
		if(!(i&1)){
			tmp+=max(abs(t[itl]-pre),abs(t[itl]-w));
			pre=t[itl++];
		}else{
			tmp+=max(abs(t[itr]-pre),abs(t[itr]-w));
			pre=t[itr--];
		}
	}
	mx=max(mx,tmp);
	write(mx);
};
auto greedymin=[](){
	int pre=w,pos=1;
	while(t[pos]<w&&pos<n) ++pos;
	if(pos==1){
		for(int i=1;i<=n;i++)
			mn+=t[i]-pre,pre=t[i];
		return write(mn,' '),void();
	}else if(pos==n&&t[n]<=w){
		for(int i=n;i;i--)
			mn+=pre-t[i],pre=t[i];
		return write(mn,' '),void();
	}
	int pps=pos-1; if(pos+1==w&&pos==w) pos++,pps=pos-1;
	int itl=pps,itr=pos,tmp=0;
	for(int i=pos;i<=n;i++) tmp+=min(abs(t[i]-pre),abs(t[i]-w)),pre=t[i];
	pre=w;
	for(int i=pps;i;i--) tmp+=min(abs(t[i]-pre),abs(t[i]-w)),pre=t[i];
	mn=tmp;
	write(mn,' ');
};
namespace WSN{
	inline short main(){
		wsn=freopen("a.in","r",stdin);
		wsn=freopen("a.out","w",stdout);
		srand(time(NULL)^clock());
		n=read(); w=read();
		for(int i=1;i<=n;i++){
			t[i]=read();
		}if(!w) return task(),0;
		sort(t+1,t+n+1);
		greedymin(); greedymax();
		return 0;
	}
}
signed main(){return WSN::main();}

T2 保险箱

感觉提议描述很不清楚,考试的时候根本不知道他要我求什么。。。

显然考试之后还有很多人跟我是一样的,都理解错题意了。。。

所以这题直接去洛谷上面瞅题解吧,没啥好说的了,我反正是伞兵做法。。。。(逃)

洛谷题解

b
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace AE86{
	FILE *wsn;
	#define gc getchar
	auto read=[](){
		int x=0,f=1;char ch=gc();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=gc();} return x*f;
	};
	auto write=[](int x,char opt='\n'){
		char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
		do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
		for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
	};
}using namespace AE86;

const int NN=250005;
int n,k,m[NN],tot;
auto check=[](int x){
	for(int i=tot;i;i--){
		if(!(m[i]%x)) return false;
		if(m[i]<x) break;
	}return true;
};
inline int gcd(int a,int b){return b?gcd(b,a%b):a;};
namespace WSN{
	inline short main(){
		wsn=freopen("b.in","r",stdin);
		wsn=freopen("b.out","w",stdout);
		n=read(); k=read();
		for(int i=1;i<=k;i++)m[i]=read();
		int rng=gcd(m[k],n);
		for(int i=1;i<k;i++)m[i]=gcd(m[i],rng);
		sort(m+1,m+k);tot=unique(m+1,m+k)-m-1;
		int ans=rng;
		for(int i=1;i*i<=rng;i++)if(!(rng%i)){
			if(i<ans&&check(i)) ans=i;
			if(rng/i<ans&&check(rng/i)) ans=rng/i;
		}
		write(n/ans);
		return 0;
	}
}
signed main(){return WSN::main();}

T3 追逐

原题大作战系列

我的题解链接

洛谷原题链接

c
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
	return x*f;
}
const int NN=1e5+2;
int n,v,p[NN],sum[NN];
int up[NN][101],dw[NN][101],ans;
vector<int> g[NN];
inline void dfs(int f,int x){
    sum[x]+=p[f];
    for(int i=0;i<g[x].size();i++){
        int y=g[x][i];if(y==f) continue;
        dfs(x,y); sum[x]+=p[y];
    }
}
inline void dp(int f,int x){
    for(int i=1;i<=v;i++){
        up[x][i]=sum[x];
        dw[x][i]=sum[x]-p[f];
    }
    for(int i=0;i<g[x].size();i++){
        int y=g[x][i];
        if(y==f) continue;
        dp(x,y);
        for(int j=1;j<v;j++)
            ans=max(ans,up[x][j]+dw[y][v-j]);
        for(int j=1;j<=v;j++){
            up[x][j]=max(up[x][j],max(up[y][j],up[y][j-1]+sum[x]-p[y]));
            dw[x][j]=max(dw[x][j],max(dw[y][j],dw[y][j-1]+sum[x]-p[f]));
        }
    }
    reverse(g[x].begin(),g[x].end());
    for(int i=1;i<=v;i++){
        up[x][i]=sum[x];
        dw[x][i]=sum[x]-p[f];
    }
    for(int i=0;i<g[x].size();i++){
        int y=g[x][i];
        if(y==f) continue;
        for(int j=1;j<v;j++)
            ans=max(ans,up[x][j]+dw[y][v-j]);
        for(int j=1;j<=v;j++){
            up[x][j]=max(up[x][j],max(up[y][j],up[y][j-1]+sum[x]-p[y]));
            dw[x][j]=max(dw[x][j],max(dw[y][j],dw[y][j-1]+sum[x]-p[f]));
        }
    }
    ans=max(ans,max(up[x][v],dw[x][v]));
}
namespace WSN{
    inline int main(){
		FILE *wsn=freopen("c.in","r",stdin);
		wsn=freopen("c.out","w",stdout);
        n=read(); v=read(); if(!v) {puts("0");return 0;}
        for(int i=1;i<=n;i++) p[i]=read();
        for(int i=1;i<n;i++){
            int x=read(),y=read();
            g[x].push_back(y);
            g[y].push_back(x);
        }dfs(0,1); dp(0,1);
        printf("%lld\n",ans);
        return 0;
    }
}
signed main(){return WSN::main();}

T4 字符串

我看不懂题解,于是去看了洛谷上的题解

d
#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace AE86{
	FILE *wsn;
	#define gc getchar
	auto read=[](){
		int x=0,f=1;char ch=gc();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=gc();} return x*f;
	};
	auto write=[](int x,char opt='\n'){
		char ch[20];short len=0;if(x<0)x=~x+1,putchar('-');
		do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
		for(short i=len-1;i>=0;--i){putchar(ch[i]);}putchar(opt);
	};
	#define mzs
}using namespace AE86;
const int NN=5e5+5;
int n,q,a[NN],l,r;
char s[NN];
namespace segment_tree{
	#define lid (id<<1)
	#define rid (id<<1|1)
	#define mid ((l+r)>>1)
	struct node{
		int ls,rs,ms,sm;
		node(){ls=rs=ms=sm=0;}
		node(int ls,int rs,int ms,int sm):ls(ls),rs(rs),ms(ms),sm(sm){}
		node operator+(const node&x)const{
			node ret;
			ret.ls=max(ls,sm+x.ls);
			ret.rs=max(x.rs,x.sm+rs);
			ret.ms=max(max(ret.ls,ret.rs),max(x.ls+rs,max(ms,x.ms)));
			ret.sm=sm+x.sm;
			return ret;
		}
	}w[NN<<2];
	inline void pushup(int id){w[id]=w[lid]+w[rid];}
	inline void build(int id,int l,int r){
		if(l==r)return w[id]=node(a[l],a[l],a[l],a[l]),void();
		build(lid,l,mid);build(rid,mid+1,r);pushup(id);
	}
	inline node query(int id,int l,int r,int L,int R){
		if(L<=l&&r<=R) return w[id]; node ret;
		if(L<=mid) ret=query(lid,l,mid,L,R)+ret;
		if(R>mid) ret=ret+query(rid,mid+1,r,L,R);
		return ret;
	}
}
segment_tree::node ans;
auto solve=[](){
	l=read(); r=read();ans=segment_tree::query(1,1,n,l,r);
	write(ans.ms-ans.sm);
};
namespace WSN{
	inline short main(){
		wsn=freopen("d.in","r",stdin);
		wsn=freopen("d.out","w",stdout);
		n=read();scanf("%s",s+1);
		for(int i=1;i<=n;i++)if(s[i]=='C') a[i]=1;else a[i]=-1;
		segment_tree::build(1,1,n);q=read(); while(q--) solve();
		return 0;
	}
}
signed main(){return WSN::main();}
posted @ 2021-11-17 17:12  雪域亡魂  阅读(92)  评论(0)    收藏  举报