20200927 day22 刷题记录

1 1183

线段树板子题。过。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e5+5;
long long tree[4*N],a[N],m,n,x,y,z,d,lazy[4*N];
void pushdown(int p,int l,int r){
	int mid=(l+r)>>1;
	tree[p<<1]+=(mid-l+1)*lazy[p];
	lazy[p<<1]+=lazy[p];
	tree[p<<1|1]+=(r-mid)*lazy[p];
	lazy[p<<1|1]+=lazy[p];
	lazy[p]=0;
}
void buildtree (int p,int l,int r){
	if(l==r) {
		tree[p]=a[l];
		return ;
	}
	int mid=(l+r)>>1;
	buildtree(p<<1,l,mid);
	buildtree(p<<1|1,mid+1,r);
	tree[p]=tree[p<<1]+tree[p<<1|1];
}
void modifytree(int p,int l,int r,int ll,int rr,int x){
	if(l==ll&&r==rr){
		tree[p]+=x*(r-l+1);
		lazy[p]+=x;
		return ;
	}
	pushdown(p,l,r);
	int mid=(l+r)>>1;
	if(ll>mid) modifytree(p<<1|1,mid+1,r,ll,rr,x);
	else if(rr<=mid) modifytree(p<<1,l,mid,ll,rr,x);
	else modifytree(p<<1,l,mid,ll,mid,x),modifytree(p<<1|1,mid+1,r,mid+1,rr,x);
	tree[p]=tree[p<<1]+tree[p<<1|1];
}
long long asktree(int p,int l,int r,int askl,int askr){
	int mid=(l+r)>>1;
	if(l==askl&&r==askr) return tree[p];
	if(lazy[p]!=0) pushdown(p,l,r);
	if(mid>=askr) return asktree(p<<1,l,mid,askl,askr);
	else if(mid<askl) return asktree(p<<1|1,mid+1,r,askl,askr);
	else 
	return asktree(p<<1,l,mid,askl,mid)+asktree(p<<1|1,mid+1,r,mid+1,askr);
}
char w; 
int main(){
	scanf("%lld%lld",&n,&m);//n shu m caozuo
	for(long long i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	buildtree(1,1,n);
	for(int i=1;i<=m;i++){
		scanf(" 
%c",&w);
		if(w=='C') scanf("%lld%lld%lld",&y,&z,&d),modifytree(1,1,n,y,z,d);
		if(w=='Q') scanf("%lld%lld",&y,&z),printf("%lld
",asktree(1,1,n,y,z));
	}
	return 0;
}

2 1077

多个条件的排序?有最小不下降子序列那味了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int n;
struct node{
	int val,len;
}mono[10005];
int f[10005];
int ans,cnt;
int vis[10005];
bool cmpx(node x,node y){
	if(x.val==y.val) return x.len<y.len;
	return x.val<y.val;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&mono[i].len,&mono[i].val);
	}
	sort(mono+1,mono+n+1,cmpx);
	while(cnt<n){
		int tmp=-1;
		for(int i=1;i<=n;i++){
			if(vis[i]==1) continue;
			else if(mono[i].len>=tmp){
				tmp=mono[i].len;
				vis[i]=1;
				cnt++;
			}
		}
		ans++;
	}
	printf("%d",ans);
	return 0;
}

3 1103

01背包。重要度在迷惑你。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int m,n;
int v[10005],imp[10005];
int dp[50005];
int cmp[10005];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&v[i],&imp[i]);
	}
	for(int i=1;i<=m;i++){
		imp[i]*=v[i];
	}
	for(int i=1;i<=m;i++){
		for(int j=n;j>=v[i];j--){
			dp[j]=max(dp[j],dp[j-v[i]]+imp[i]);
		}
	}
	printf("%d",dp[n]);
	return 0;
}

4 1104

01背包。恰好装满的方案。注意这个0x3f

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int a[15];
int k;
int dp[10005];
int main(){
	for(int i=1;i<=10;i++){
		scanf("%d",&a[i]);
	}
	scanf("%d",&k);
	memset(dp,0x3f,sizeof(dp));
	dp[0]=0;
	for(int i=1;i<=10;i++){
		for(int j=i;j<=k;j++){
			dp[j]=min(dp[j],dp[j-i]+a[i]);
		}
	}
	printf("%d
",dp[k]);
	return 0;
}

5 1101

题面

任何大于 1 的自然数(N),都可以写成若干个大于等于2且小于等于(N)的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式。例如9 的质数和表达式就有四种本质不同的形式:9 = 2+5+2 = 2+3+2+2 = 3+3+3 = 2+7 。
这里所谓两个本质相同的表达式是指可以通过交换其中一个表达式中参加和运算的各个数的位置而直接得到另一个表达式。
试编程求解自然数 (N)可以写成多少种本质不同的质数和表达式。

题解

dp[i][j]表示把数字i用最小为j的质数分解的方案数。
dp[i][j] = sum(dp[i - k][k]), (j <= k <= i, k是质数)
初始化是所有质数idp[0][i]= 0
内存限制2M,欧拉筛法还是算了,直接打表。

代码

#include <cstdio>
using namespace std;
int n, dp[202][202];
bool not_prm[202] = {1,1,0,0,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,};
int main(){
      for(int i = 2; i <= 200; i++){
            if(!not_prm[i]) dp[0][i] = 1;
            for(int j = 2; j <= i; j++){
                  for(int k = j; k <= i; k++){
                  if(!not_prm[k]) dp[i][j] += dp[i - k][k];
                  }
            }
      }
      while(~scanf("%d", &n)){
            printf("%d
", dp[n][2]);
      }
      return 0;
}
要做就做南波万
原文地址:https://www.cnblogs.com/liuziwen0224/p/20200927day22-001.html