ブルーブリッジカップ全国大会準備DAY4

  1. スキー
    スキーの質問(メモ化されたdp、再帰的なdpとも呼ばれます)の質問リンクを書き直します
#include<iostream>

using namespace std;

const int N=300 +10;

int arr[N][N];
int f[N][N];
int n,m;
int res;
int dx[4]={
    
    };
int dy[4]={
    
    };

int dp(int x, int y){
    
    
    if(f[x][y]!=-1) return f[x][y];
    f[x][y]=1;
    if(x+1<=n && arr[x+1][y]<arr[x][y])
        f[x][y]=max(f[x][y],dp(x+1,y)+1);
        
    if(x-1>=1 && arr[x-1][y]<arr[x][y])
        f[x][y]=max(f[x][y],dp(x-1,y)+1);
    
    if(y+1<=n && arr[x][y+1]<arr[x][y])
        f[x][y]=max(f[x][y],dp(x,y+1)+1);
    
    if(y-1>=1 && arr[x][y-1]<arr[x][y])
        f[x][y]=max(f[x][y],dp(x,y-1)+1);
    
    return f[x][y];
}

int main(){
    
    
    cin>>n>>m;
    for(int i=1;i<=n;i++){
    
    
        for(int j=1;j<=m;j++){
    
    
            cin>>arr[i][j];
            f[i][j]=-1;
        }
    }
    
    for(int i=1;i<=n;i++){
    
    
        for(int j=1;j<=m;j++){
    
    
            res=max(res,dp(i,j));    
        }
    }
    cout<<res<<endl;
    return 0;
}
  1. 石の融合

トピックリンク

間隔dp

#include<iostream>

using namespace std;

const int N=300+10;

int arr[N];
int s[N];
int f[N][N];
int n;

int main(){
    
    
    cin>>n;
    for(int i=1;i<=n;i++){
    
    
        cin>>arr[i];
        s[i]=arr[i];
    }
    
    for(int i=1;i<=n;i++){
    
    
        s[i]+=s[i-1];
    }
    
    for(int len=2;len<=n;len++){
    
    
        for(int i=1;i-1+len<=n;i++){
    
    
            int j=i-1+len;
            f[i][j]=1e8;
            for(int k=i;k<j;k++){
    
    
                f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
            }
        }
    }
    cout<<f[1][n]<<endl;
    return 0;
}
  1. 食物連鎖
    トピックリンク

そして、アプリケーションを確認してください

#include<iostream>

using namespace std;

const int N=50000 +10;


int n,m;
int father[N];
int d[N];
int res;

int find(int x){
    
    
    if(father[x]!=x){
    
    
        int t=find(father[x]);
        d[x]+=d[father[x]]; 
        father[x]=t;
    }
    return father[x];
}

int main(){
    
    
    cin>>n>>m;
    for(int i=1;i<=n;i++){
    
    
        father[i]=i;
    }
    
    while(m--){
    
    
        int k,a,b;
        cin>>k>>a>>b;
        if(a>n || b>n){
    
    
            res++;
        }else{
    
    
            int xx=find(a);
            int yy=find(b);
            //同一类
            if(k==1){
    
    
                //在同一个集合 但是关系不是同一类
                if(xx==yy && (d[a]-d[b])%3){
    
    
                    res++;
                }else if(xx!=yy){
    
    
                    //不在同一个集合里,无法判断,则为真话
                    //合并
                    father[xx]=yy;
                    //设置关系
                    d[xx]=d[b]-d[a];
                }
            }else{
    
    
                //在同一个集合 但是关系不是a吃b
                if(xx==yy && (d[a]-d[b]-1)%3){
    
    
                    res++;
                }else if(xx!=yy){
    
    
                    //不在同一个集合
                    //合并
                    father[xx]=yy;
                    //设置关系
                    d[xx]=1+d[b]-d[a];
                }
            }
        }
        
    }
    cout<<res<<endl;
    return 0;
}
  1. 連続区間和を動的に見つける

ボード:ツリー配列||線分ツリー

トピックリンク

①線分ツリーソリューション

#include<iostream>

using namespace std;

const int N=100000 +10;

typedef struct T{
    
    
  int l,r;
  int sum;
};

T t[N*4];
int d[N*4];
int W[N*4];
int n,m;

void push_up(int u){
    
    
    t[u].sum=t[u<<1].sum+t[u<<1|1].sum;
}

void build(int u ,int l , int r){
    
    
    if(l==r){
    
    
        t[u]={
    
    l,r,W[r]};
    }else{
    
    
        t[u]={
    
    l,r};
        int m=l + r >> 1;
        build(u<<1,l,m);
        build(u<<1|1,m+1,r);
        push_up(u);
    }
}

void modify(int u, int index, int key){
    
    
    if(t[u].l==t[u].r){
    
    
        t[u].sum+=key;
    }else{
    
    
        int m=t[u].l+ t[u].r>>1;
        if(index<=m){
    
    
            modify(u<<1,index,key);
        }else{
    
    
            modify(u<<1|1,index,key);
        }
        push_up(u);
    }
}

int query(int u, int l, int r){
    
    
    if(t[u].l>=l && t[u].r<=r){
    
    
        return t[u].sum;
    }else{
    
    
        int sum=0;
        int m=t[u].l + t[u].r>>1;
        if(l<=m){
    
    
            sum+=query(u<<1,l,r);
        }
        if(r>m){
    
    
            sum+=query(u<<1|1,l,r);
        }
        return sum;
    }
}


int main(){
    
    
    cin>>n>>m;
    for(int i=1;i<=n;i++){
    
    
        cin>>W[i];
    }
    
    build(1,1,n);
    
    while(m--){
    
    
        int k,a,b;
        cin>>k>>a>>b;
        if(k==1){
    
    
            modify(1,a,b);
        }else{
    
    
            cout<<query(1,a,b)<<endl;
        }
    }
    
    return 0;
}

②ツリー配列

#include <iostream>
using namespace std; 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

const int N=100000 +10;

int arr[N];
int tre[N];
int n,m;
int k,a,b;
int lowbit(int x){
    
    
	return x & -x;
}

void add(int index, int key){
    
    
	for(int i=index;i<=n;i+=lowbit(i)){
    
    
		tre[i]+=key;
	}
}

int query(int index){
    
    
	int res=0;
	for(int i=index;i;i-=lowbit(i)){
    
    
		res+=tre[i];
	}
	return res;
}

int main(int argc, char *argv[]) {
    
    	
	cin>>n>>m;
	for(int i=1;i<=n;i++){
    
    
		cin>>arr[i];
		add(i,arr[i]);
	}
	
	while(m--){
    
    
		cin>>k>>a>>b;
		if(!k){
    
    
			cout<<query(b)-query(a-1)<<endl;
		}else{
    
    
			add(a,b);
		}
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/BOWWOB/article/details/109348491