Zut_round 6

A、经典LIS模板(poj2533)

题意:求最长严格上升子序列

#include
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e3+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
int a[N],dp[N];
int main()
{
	int n=read();for(int i=1;i<=n;++i)a[i]=read(),dp[i]=1;
	int ans=1;
	for(int i=2;i<=n;++i){
		for(int j=1;j<i;++j)
			if(a[j]<a[i])dp[i]=max(dp[j]+1,dp[i]);
		ans=max(ans,dp[i]);
	}
	cout<<ans<<line;
	return 0;
}

B、多阶段决策dp模板(hdu2059)

题意:长为L的赛道上,乌龟在电车有无电时的速度x、y能否比恒定速度v的兔子先到达终点,赛道上有n个带属性的充电站。

思路:相同路程比较时间,定义dp[i]为第j(ji));

#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e2+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
double L,a[N],dp[N];
int main()
{
    int n,s,t,v,x,y;
    while(cin>>L){
        cin>>n>>s>>t>>v>>x>>y;
        for(int i=1;i<=n;++i)a[i]=read(),dp[i]=INT_MAX;
        a[n+1]=L;dp[0]=0;dp[n+1]=INT_MAX;
        for(int i=1;i<=n+1;++i)for(int j=0;j<i;++j){
            double mx=0;
            if(a[i]-a[j]>s)mx=(a[i]-a[j]-s)/y+s*1.0/x;
            else mx=(a[i]-a[j])/x;
            mx+=dp[j];
            if(j)mx+=t;
            dp[i]=min(dp[i],mx);
        }
        if(dp[n+1]<L/v)cout<<"What a pity rabbit!"<<line;
        else cout<<"Good job,rabbit!"<<line;
    }
    return 0;
}

C、CodeForces - 1077A

题意:k次操作,加a减b依次进行,问最后结果

#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e3+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
int main()
{
	int T=read();
	while(T--){
		LL a=read(),b=read(),k=read();
		LL ans=k/2*(a-b);
		if(k&1)ans+=a;
		cout<<ans<<line;
	}
	return 0;
}

D、CodeForces - 1077B

题意:各个公寓灯有0、1两种状态,形为101的公寓会受到干扰,求最小关掉灯的个数使各个公寓都不受干扰。

思路:实际就是找有多少个10101与101,最小关灯次数都为1,其他如1010101、101010101等等都可以转化为这两种情况,统计即可。

#include
#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=1e2+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
int main()
{
	string str="";int a;
	int n=read();for(int i=1;i<=n;++i)a=read(),str+='0'+a;
	str+="000000";int i=0,ans=0;
	while(i<=n){
		if(str.substr(i,5)=="10101")ans++,i+=4;
		else if(str.substr(i,3)=="101")ans++,i+=2;
		else i++;
	}
	cout<<ans<<line;
	return 0;
}

E、CodeForces - 1077C

题意:n个数中判断是否可以删除某个数,使剩下数中的某个数是其他所有数的和

思路:记录总和,循环依次判断删除这个数能否满足条件

#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=2e5+9;
#define line '\n'
#define gt getchar()
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
LL sum,a[N];
unordered_map<LL,int> mp;
int main()
{
	int n=read();for(int i=1;i<=n;++i)a[i]=read(),sum+=a[i],mp[a[i]]++;
	vector<int> V;
	for(int i=1;i<=n;++i){
		mp[a[i]]--;
		LL t=sum-a[i];
		if(!(t&1)&&mp[t/2])V.push_back(i);
		mp[a[i]]++;
	}
	cout<<V.size()<<line;
	for(auto it:V)cout<<it<<" ";
	cout<<line;
	return 0;
}

F、CodeForces - 1077D

题意:n个数中选出k个数,使这k个数在n个数的重复次数最多
思路:要求重复次数最多,直接二分重复次数判断此时满足重复次数的个数能否大于k个

#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=2e5+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
unordered_map<int,int> mp;
int n,k,x;
bool judge(int t)
{
	int num=0;
	for(auto it:mp)num+=it.second/t;
	return num>=k;
}
int main()
{
	n=read(),k=read();for(int i=1;i<=n;++i)x=read(),mp[x]++;
	int L=1,R=n,ans;
	while(L<=R){
		if(judge(mid)){
			ans=mid;
			L=mid+1;
		}
		else R=mid-1;
	}
	for(auto it:mp){
		if(k==0)break;
		int y=min(k,it.second/ans);
		k-=y;
		while(y--)cout<<it.first<<" ";
	}
	cout<<line;
	return 0;
}

G、CodeForces - 1077E

题意:定义序列F:{x,2x,4x…}
长为n的数组a,根据a[i]出现的次数求最大满足序列F的序列和

思路:虽然a[i]范围达到1e9但各个a[i]出现次数最多为n,可以选择F序列的第一项进行二分

#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=2e5+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
map<int,int> mp;
int a[N];
int main()
{
	int n=read(),x;for(int i=1;i<=n;++i)x=read(),mp[x]++;
	int k=0,m=0;LL ans=0;
	for(auto it:mp)a[++k]=it.second,m=max(m,a[k]);
	sort(a+1,a+k+1);
	for(int i=1;i<=m;++i){
		int t=i,L=1;
		LL sum=0;
		while(1){
			L=lower_bound(a+L,a+k+1,t)-a;
			if(L>k)break;
			L++;
			sum+=t;
			t<<=1;
		}
		ans=max(ans,sum);
	}
	cout<<ans<<line;
	return 0;
}

H、CodeForces - 1077F1

题意:求n个数中选出x个数最大和,但任意连续k个数中必须有选中的.

思路:定义dp[i][j]为前i个数中选j个的最大值,其中第i个必选,又因有k的限制,最后k个数必有一选才能合法化
转移方程dp[i][j]=max(dp[i][j],dp[p][j-1]+a[i])其中max(0,i-k)<=p

#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=2e2+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
#define inf 0x3f3f3f3f3f3f3f3f
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
LL dp[N][N],a[N]; 
int main()
{
	int n=read(),k=read(),x=read();
	for(int i=1;i<=n;++i)a[i]=read();
	LL ans=-1;memset(dp,-inf,sizeof(dp));
	dp[0][0]=0;
	for(int i=1;i<=n;++i)for(int j=1;j<=x;++j)for(int p=max(0,i-k);p<i;++p)
		dp[i][j]=max(dp[i][j],dp[p][j-1]+a[i]);
	for(int i=n-k+1;i<=n;++i)ans=max(ans,dp[i][x]);
	cout<<ans<<line;
    return 0;
}

I、CodeForces - 1077F2
单调队列维护dp[p][j-1]单增

#include
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int N=5e3+9;
#define line '\n'
#define gt getchar()
#define mid ((L+R)>>1)
#define inf 0x3f3f3f3f3f3f3f3f
int read(){int x=0,op=1;char c=gt;while(!isdigit(c)){if(c=='-')op=-1;c=gt;}while(isdigit(c))x=x*10+c-48,c=gt;return x*op;}
LL dp[N][N],a[N],Q[N],que[N];
int main()
{
	int n=read(),k=read(),x=read();
	for(int i=1;i<=n;++i)a[i]=read();
	LL ans=-1;memset(dp,-inf,sizeof(dp));
	dp[0][0]=0;
	for(int j=1;j<=x;++j){
		int L=0,R=1;Q[0]=0;
		for(int i=1;i<=n;++i){
			while(L<R&&Q[L]<i-k)L++;
			dp[i][j]=dp[Q[L]][j-1]+a[i];
			while(L<R&&dp[i][j-1]>=dp[Q[R-1]][j-1])R--;
			Q[R++]=i;
		}
	}
	for(int i=n-k+1;i<=n;++i)ans=max(ans,dp[i][x]);
	cout<<ans<<line;
    return 0;
}

你可能感兴趣的:(codeforces)