- スキー
スキーの質問(メモ化された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;
}
- 石の融合
間隔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;
}
- 食物連鎖
トピックリンク
そして、アプリケーションを確認してください
#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;
}
- 連続区間和を動的に見つける
ボード:ツリー配列||線分ツリー
①線分ツリーソリューション
#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;
}