A.三人の友
問題の意味
数に三\(A、B、C \) 、各数はすることができ(、+ 1 -1 \)\または変わらないが、それぞれの操作の数は、かつての後、最大で尋ね| A'-B」|(\ + | A'-C '| + | B'-C' | \) 最小。
思考
その後、暴力的な列挙各オペランド、および後の値は、ライン上で最小の結果を記録します
コード
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int T,a[5];
int main(){
scanf("%d",&T);
while(T--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
LL res=0x3f3f3f3f3f3f3f;
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
for(int k=-1;k<=1;k++){
int x=a+i,y=b+j,z=c+k;
res=min(res,1ll*abs(x-y)+abs(x-z)+abs(y-z));
}
printf("%lld\n",res);
}
return 0;
}
B.雪歩行ロボット
問題の意味
こうしたから文字を削除するには、できるだけ必要とし、文字列、パス記述(\)(0,0)\バックアップできる切除文字列に応じてダウンする(\)(0,0)\、および加えて、\((0,0)\)二度の点を通過しません
思考
統計'U'、 'R'、 'D' の数、 'L'、表記\(U-は、R、D、L \) 。((0,0)\)\バックに行き始め\((0,0)\) 、その後、明らかに\(U = D、R = L \)にする、あなたの最初の必要性U = D =(\分(U、D)は、R = L =分(R&LT、L)\)、最初に従う、右、次の、および、左円を完成させることができます。この時点で、削除場合、ことに留意すべきで\(U = D = 0 \ ) または\(R&LT L = 0 = \)だけ元、その後もちろん、それはこの場合のみであるため、すぐに次にワンステップバックを移動することができあなたがより多く取る場合には、この特殊なケースが出て判断しなければならないような方法のバックは、道のポイントに沿って、2の後になります。
コード
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
int T;
char s[MAXN];
int main(){
scanf("%d",&T);
while(T--){
scanf("%s",s+1);
int n=strlen(s+1);
int U=0,R=0,D=0,L=0;
for(int i=1;i<=n;i++)
if(s[i]=='U') U++;
else if(s[i]=='R') R++;
else if(s[i]=='D') D++;
else if(s[i]=='L') L++;
U=D=min(U,D);
R=L=min(L,R);
if(!U&&!D&&R&&L) L=R=1;
if(!L&&!R&&U&&D) U=D=1;
printf("%d\n",U+D+L+R);
for(int i=1;i<=U;i++) printf("U");
for(int i=1;i<=R;i++) printf("R");
for(int i=1;i<=D;i++) printf("D");
for(int i=1;i<=L;i++) printf("L");
printf("\n");
}
return 0;
}
C.もう一つの壊れたキーボード
問題の意味
文字列に\(S \)、\ (K \)文字、Q \(S \)のみが含まれているの\(K \)種のサブストリングの文字の数。
思考
仮定(S [I、J] \ \) 、正当それは正当なサブストリング必要があり、それが寄与回答を生成する(\ \ FRAC {(J = I + 1)(J-I + 2)} {2 } \) 。
したがって、各その後、答えはライン上に蓄積して、正当な範囲のために選出されました。
コード
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=2e5+10;
int n,k,can[300];
char s[MAXN],temp[10];
int main(){
scanf("%d%d",&n,&k);
scanf("%s",s+1);
for(int i=1,x;i<=k;i++){
scanf("%s",temp);
can[temp[0]]=1;
}
LL ans=0;
int j=0;
for(int i=1;i<=n;i++){
if(can[s[i]]) j++;
else{
ans+=1ll*j*(j+1)/2;
j=0;
}
}
ans+=1ll*j*(j+1)/2;
printf("%lld\n",ans);
return 0;
}
D.削除一つの要素
問題の意味
シーケンスするには、種の数、サブQシーケンスの長さは最長の連続上昇からアップ削除される可能性があります。
思考
セット\(F [I] [0/1 ] \) 最初のと同様\(I \)端におけるビットは、未削除/数が数列における最長の連続的増加の長さを得ることができる削除しました。
最初の\(F [i]が[0 ] \) 、この状態ではうまく、長さが最長の共通のサブシーケンスを連続的に上昇する:
\ [F [I] [0] = F [I-1] [0] +。 1 \([I]>
[I-1])\\ F [i]が[0] = 1 \([I] \ルA [I-1])\] と\(F [i]が[1] \)この状態は困難ではないで、この状態で発生する可能性がある二つの状況があるが明らかである:
1. \([I] \) 、受信した\([I-1] \) 端と削除します上昇後の連続したサブシーケンスの最大数。
2. \([I] \)での\([I-2] \) の連続シーケンスを削除しないの数の最大増加の終了後、明らかにこのような状況である[1-(\ 1] \)を削除。
\ [F [i]が[1 ] = F [I-1] [1] +1 \([I]> [I-1])\\ F [i]が[1] = F [I-2 ] [0] +1 \( [I]> [I-2])\\ F [i]が[1] = 1( いずれにせよ)\]
#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
int n,a[MAXN],f[MAXN][2];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int ans=0;
for(int i=1;i<=n;i++){
f[i][0]=f[i][1]=1;
if(a[i]>a[i-1]){
f[i][0]=f[i-1][0]+1;
f[i][1]=f[i-1][1]+1;
}
if(a[i]>a[i-2]) f[i][1]=max(f[i][1],f[i-2][0]+1);
ans=max(ans,max(f[i][0],f[i][1]));
}
printf("%d\n",ans);
return 0;
}
反対のパリティ最寄りのE.
問題の意味
\(N- \)シーケンス番号\(A_1、A_2、...、A_N \) 、最初の\(I \)数はジャンプ時間をジャンプすることができます\(I「= I-a_iを (I- a_iを\ GEQ 1)\)番号または\(I「= I + a_iを (I + a_iを\当量N)\) 番号に、ホップ毎の最小数は、数回に尋ねたように)a_iを\(\と\ (A_ {I「} \)異なるパリティ。
思考
論理的に言えば、この質問は、検索によって解決することができ、もちろん、検索時間をダイレクトアウトになり、全体の検索を解決することができた後、私は再びビルド・マップへの道を変えて、私は、WAのメモリを追加します。
話をどのようにビルド・マップに
知られている場合は、\(ans_i \) 、そしてもし\(J + a_j = I \ ) と\(a_j \%2%2 = a_iを\) 、そう\(ans_j = ans_i + 1 \
) ので、もし(a_iを\%I + 2 = {a_iを} A_ \%2 \)\、それを確立することができる\(I + a_i-> I \ ) 有向エッジ、
\(I-a_iを\)と\( I \)同様に
、明らかに簡単に(ans_i = 1 \)\すべての位置で、あなたはこれらの位置から開始することができますことは、広い検索することができ
コード
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int MAXN=2e5+10;
int n,a[MAXN],ans[MAXN];
int head[MAXN],to[MAXN*2],nxt[MAXN*2],tot=0;
queue<int> que;
void add(int u,int v){
to[++tot]=v;nxt[tot]=head[u];head[u]=tot;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(ans,0x3f,sizeof(ans));
for(int i=1;i<=n;i++){
if(i-a[i]>=1&&a[i-a[i]]%2==a[i]%2) add(i-a[i],i);
if(i+a[i]<=n&&a[i+a[i]]%2==a[i]%2) add(i+a[i],i);
}
for(int i=1;i<=n;i++)
if(i-a[i]>=1&&a[i-a[i]]%2!=a[i]%2||i+a[i]<=n&&a[i+a[i]]%2!=a[i]%2)
ans[i]=1,que.push(i);
while(!que.empty()){
int u=que.front();que.pop();
for(int i=head[u];i;i=nxt[i])
if(ans[to[i]]>ans[u]+1){
ans[to[i]]=ans[u]+1;
que.push(to[i]);
}
}
for(int i=1;i<=n;i++) printf("%d ",ans[i]==inf?-1:ans[i]);
return 0;
}
F.二つのブラケットシーケンス
問題の意味
配列の2つのブラケット\(S1、S2 \) 、最短配列括弧仕様の構築を必要とする(ANS \)\、および満足\(S1、S2 \)の(ANS \)\配列です。
思考
全体の検索は、
すでにシーケンスを構築していることを前提と\((I、J、K)\) :\
(I \) :\ (S1 \)の前に\(私は\)ビットは、現在のシーケンスのサブシーケンスである
J(\ \):\ (S2 \)の前に\(J \)ビットは、現在のシーケンスのサブシーケンスである
\(K \):\ (K =左カッコ-右括弧\)
その後、あなたはから必要な\((0、0、 0)\)するように構成され((len_ {S1}、\
\ len_ {S2}、0)) この点は、3次元空間の三重項とみなされる場合、それが実際に要求されている\((0,0 、0)\)に\((len_ {S1}、 len_ {S2}、0)\) の最短経路です。
一点から別の点の距離にこれがあるので(1 \)\、最短直接全体の検索を見つけます。
二点間の関係に移る
既知ブラケット配列の((I、J、K)\)\、
配列を追加する場合(ポイントとして理解することができる「(」1 ((I、J、K \ )\) )別のポイントに移動します
もし\(S1 [I + 1] = '('、S2 [J + 1] = '(' \) 、シーケンスを構成することができる\((I + 1、J + 1、K + 1)\) (点\ ((I、J、K) - 。。。>(I + 1、J + 1、K + 1)\) )
であれば\(S1 [I + 1] = '('、S2 [J + 1] \ありません= ' (「\) 、シーケンスを構成することができる(。。(I + 1、J、K + 1)\)\(点。\((I、J、K)。 - >(I + 1、J、K + 1)\) )
場合\(S1 [I + 1]ない\ = '('、S2 [J + 1] = '(' \) 、シーケンスを構成することができる((I、J + 1、K + 1)\)\(点\ ((I、J、K) - >(I、J 1 +、K + 1)\) )
2.あなたは''を追加した場合)(この時のシーケンスに\(K \ GEQ 0 \) 、規制しているためブラケット配列は、任意のプレフィックス右括弧)は、左括弧よりもすることができない
場合\(S1 [I + 1] = ')'、S2 [J + 1] = ')' \) 、シーケンスを構成することができる((\ 。+ 1 I、J + 1 ,. 1-K)\)。 (点\((I、J、K ) - >(I + 1、J + 1、。1-K)\) )
の場合\(S1 [I + 1] = ')'、S2 [J + 1]ない\ = ')' \) 、シーケンスを構成することができる\((I + 1、J、K-1)\) (点(\ (I、J、K) - >(。。I + 1、J、K-1)\) )
であれば\(S1 [I + 1] \ない= ')'、S2 [J + 1] = ')' \ )、配列を構成することができる\(。。(I、J + 1、K-1)\)(点- >(I、J + 1、K-1)\。\((I、J、K)を))
に、次に\ ((0,0,0)\)全体の検索を行うための開始点として。
エンドポイントから広い探索経路を記録する\((len_ {S1}、 len_ {S2}、0)\) 構築パスリバース、答えです。
#include <bits/stdc++.h>
using namespace std;
char s1[210],s2[210];
int n,m;
struct Node{
int i,j,k;
}f[210][210][410];
queue<Node> que;
void bfs(){
memset(f,-1,sizeof(f));
f[0][0][0]=(Node){0,0,0};
que.push((Node){0,0,0});
while(!que.empty()){
Node u=que.front();que.pop();
int i=u.i,j=u.j,k=u.k,vi,vj,vk;
vi=i+(s1[i+1]=='(');
vj=j+(s2[j+1]=='(');
vk=k+1;
if(vk<=n+m&&f[vi][vj][vk].i==-1){
f[vi][vj][vk]=u;
que.push((Node){vi,vj,vk});
}
vi=i+(s1[i+1]==')');
vj=j+(s2[j+1]==')');
vk=k-1;
if(vk>=0&&f[vi][vj][vk].i==-1){
f[vi][vj][vk]=u;
que.push((Node){vi,vj,vk});
}
}
}
int main(){
scanf("%s%s",s1+1,s2+1);
n=strlen(s1+1);
m=strlen(s2+1);
bfs();
string ans;
int i=n,j=m,k=0;
while(i||j||k){
Node u=f[i][j][k];
if(k>u.k) ans="("+ans;
else ans=")"+ans;
i=u.i;j=u.j;k=u.k;
}
cout<<ans<<endl;
return 0;
}