noip 2018 模拟赛2

T 1 T_1 T1——one(3004)

Description:

一个只包含0,1的 n ⋅ m n \cdot m nm的矩阵,可以无数次任意交换两行,求交换后最大的1的面积。
n , m ≤ 3000 n,m\le 3000 n,m3000

Solution:

  • 这里的操作是可以交换行,那么我们可以贪心地,找出对于每一行上的1的最大连续长度,再通过列的前缀和(后缀和)求出当前长度为 j j j的最长宽度。

Code:

#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}

const int N=3010;

int n,m;
char s[N];
bool mp[N][N];
int mx[N],cnt[N][N];

int main(){
//	freopen("one.in","r",stdin);
//	freopen("one.out","w",stdout);
	scanf("%d%d",&n,&m);
	REP(i,1,n){
		scanf("%s",s+1);
		REP(j,1,m)  if(s[j]=='1') mp[i][j]=1;
	}
	
	REP(i,1,n) DREP(j,m,1) mx[j]=mp[i][j]?mx[j+1]+1:0,cnt[j][mx[j]]++;
	
	int ans=0;
	DREP(j,m,1) REP(i,1,m-j+1) cnt[i][j]+=cnt[i][j+1],chkmax(ans,cnt[i][j]*j);
	printf("%d\n",ans);	
	return 0;
} 

T 2 T_2 T2——calendar(3723)

Description:

有一个 n ⋅ m n \cdot m nm的矩阵, q q q次操作, 每次操作为 ( v , u , k ) (v,u,k) (v,u,k),将矩阵中第 ( v + i , u − i + j ) (v+i,u-i+j) (v+i,ui+j)格子上的权值加上 C j i C_j^i Cji ( j ≥ k , i ∈ [ 0 , j ] ) (j \ge k,i\in[0,j]) (jk,i[0,j])
n , m ≤ 300 , q ≤ 5 ∗ 1 0 6 n,m\le300,q\le5*10^6 n,m300,q5106

Solution:

  • 大概就是找规律题,发现每次操作都是将做一个杨辉三角,

Code:

#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define ll long long

const int mod=998244353,N=302;

int n,m,q,x;

void Add(int &x,int y){
	x+=y;
	if(x>=mod)x-=mod;
}

int Rad(){
	x=(1ll*100000005*x+20150823)%mod;
	return x/100;	
}

struct p20{
	int C[N][N];
	int mp[N][N];

	void Init(){
		C[0][0]=1;
		SREP(i,1,N){
			C[i][0]=C[i][i]=1;
			SREP(j,1,i) Add(C[i][j]=C[i-1][j-1],C[i-1][j]);
		}
	}
	
	void solve(){
		
		Init();
		
		while(q--){
			int v=Rad()%n+1;
			int u=Rad()%m+1;
			int k=Rad()%(n+m-v-u+1);
		
			REP(j,k,2*(n+m)){
				if(u+v+j>n+m)break;
				REP(i,0,j){
					if(v+i>n)break;
					if(u-i+j>m)continue;
					Add(mp[v+i][u-i+j],C[j][i]);
				}
			}
		}
		REP(i,1,n) REP(j,1,m) printf("%d%c",mp[i][j]," \n"[j==m]);
	}

}p1;

struct p100{
	int dp[N][N][N<<1];
	
	void solve(){
		REP(i,1,q){
			int u=Rad()%n+1;
			int v=Rad()%m+1;
			int k=Rad()%(n+m-u-v+1);
			dp[u][v][k]++;
		}
	
		REP(i,1,n){
			REP(j,1,m){
				Add(dp[i][j][0],(dp[i][j-1][0]+dp[i-1][j][0])%mod);
				REP(k,0,n+m+1) Add(dp[i][j][k],(dp[i-1][j][k+1]+dp[i][j-1][k+1])%mod);
				printf("%d%c",dp[i][j][0]," \n"[j==m]);
			}
		}
	}
}p2;

int main(){
//	freopen("calendar.in","r",stdin);
//	freopen("calendar.out","w",stdout);
	scanf("%d%d%d%d",&n,&m,&q,&x);
	
	if(n<=100 && q<=100)p1.solve();
	else p2.solve();
	
	return 0;
}

T 3 T_3 T3——yummy

Description:

Solution:

Code:

#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define ll long long
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
template<class T>inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
template<class T>inline void Rd(T &x){
	x=0;char c;
	while((c=getchar())<48);
	do x=(x<<1)+(x<<3)+(c^48);
	while((c=getchar())>47);
}

const int N=4002,M=2e4+2;

int n,p;
struct node{
	int c,h,t,id;
	bool operator<(const node &_)const{
		return t<_.t;
	}
}A[N];
int q; 

struct p50{
	int tot;
	struct bag{
		int c,w;
	}mp[N];
	int dp[N];
	void solve(){
		
		int D,V;
		REP(i,1,q){
			Rd(D),Rd(V);
				
			tot=0;
			memset(dp,0,sizeof(dp));
			 
			REP(j,1,n)  if(D>=A[j].t && D<=A[j].t+p-1)mp[++tot]=(bag){A[j].c,A[j].h};
			
			REP(j,1,tot) DREP(k,V,mp[j].c) chkmax(dp[k],dp[k-mp[j].c]+mp[j].w);
		
			int ans=0;
			REP(j,0,V) chkmax(ans,dp[j]);
			printf("%d\n",ans);
		
		}
		
	}
}p1;

struct p100{
	
	int dp1[N][N],dp2[N][N]; 
	
	void solve(){
		REP(i,1,n) A[i].id=A[i].t/p;
		REP(i,1,n) {
			if (A[i].id>A[i-1].id) REP(j,A[i].c,N-1) dp1[i][j]=A[i].h;
			else {
				memcpy(dp1[i],dp1[i-1],sizeof(dp1[i]));
				DREP(j,N-1,A[i].c) chkmax(dp1[i][j],dp1[i-1][j-A[i].c]+A[i].h);
			}
		}
	
		DREP(i,n,1){
			if (i==n||A[i].id<A[i+1].id)REP(j,A[i].c,N-1) dp2[i][j]=A[i].h;
			else {
				memcpy(dp2[i],dp2[i+1],sizeof(dp2[i]));
				DREP(j,N-1,A[i].c) chkmax(dp2[i][j],dp2[i+1][j-A[i].c]+A[i].h);
			}
		}	
		
		int D,V,l,r;
		while(q--){
			Rd(D),Rd(V);
			l=r=0;
			REP(i,1,n) if(D>=A[i].t && D<=A[i].t+p-1){
				if(!l)l=i;
				r=i;
			}
			if(A[l].id==A[r].id){
				if(r<n && A[r+1].id==A[r].id)l=0;
				else r=0;
			}
			int ans=0;
			REP(j,0,V) chkmax(ans,dp1[r][j]+dp2[l][V-j]);
			printf("%d\n",ans);
		}
	}
}p2;

int main(){
//	freopen("yummy.in","r",stdin);
//	freopen("yummy.out","w",stdout);
	Rd(n),Rd(p);
	REP(i,1,n) Rd(A[i].c),Rd(A[i].h),Rd(A[i].t);
	sort(A+1,A+1+n);
	Rd(q);
	
	if(n<=50) p1.solve();
	else p2.solve();
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值