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
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)
templateinline bool chkmax(T &x,T y){return x

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
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 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
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 ll long long
templateinline bool chkmax(T &x,T y){return xinline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templateinline 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].t && D<=A[i].t+p-1){
				if(!l)l=i;
				r=i;
			}
			if(A[l].id==A[r].id){
				if(r

你可能感兴趣的:(贪心,dp,分块,离线赛-总结)