Huawei 2021バッチの筆記テスト問題

概要:データ構造fwが覆されました...

T1

トピックの主なアイデア:長さkの2つの文字列a、ba、bを与えるA b、長さnの2つの文字列c、dc、dc d (k <= n)(k <= n)k<=n 、最小llを見つけるLその結果、C、DC、Dc dのlの先頭にある長さk部分文字列は、a、ba、bとまったく同じです。A bが一致します。
n、k <= 1 e 6 n、k <= 1e6n k<=1 e 6

今行ってる!また、筆記試験の必需品です!

(実際には、n個のゲームでもハッシュがあります。誰もがそれを理解しています。ハッシュをよく学んだら、書かれたテストに合格する必要があります。jpg)

C ++コード:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ull unsigned long long
#define maxn 10000005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline int read()
{
    
    
	int x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {
    
    if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {
    
    x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}

ull h1[maxn],h2[maxn],p1,p2,B[maxn];
int n,k,x;

inline ull gh(int l,int r,int opt)
{
    
    
	if(opt==1) return h1[r]-h1[l-1]*B[r-l+1];
	else return h2[r]-h2[l-1]*B[r-l+1];
}

int main()
{
    
    
	freopen("t1.in","r",stdin);
	k=read(); B[0]=1; rep(i,1,maxn-5) B[i]=B[i-1]*233;
	rep(i,1,k) x=read(),p1=p1*233+x;
	rep(i,1,k) x=read(),p2=p2*233+x;
	n=read();
	rep(i,1,n) x=read(),h1[i]=h1[i-1]*233+x;
	rep(i,1,n) x=read(),h2[i]=h2[i-1]*233+x;
	int F=0;
	rep(l,1,n)
	{
    
    
		int r=l+k-1; if(r>n) break;
		ull x1=gh(l,r,1),x2=gh(l,r,2);
		if(x1==p1&&x2==p2) {
    
    F=l; break;}
	}
	cout<<F<<endl;
	return 0;
}

T2

トピックの主な考え方:n * mの行列が与えられた場合、一度に4方向で自分の体重より少ない場所に行くことができ、開始点を選択して最長の経路を見つける必要があります。
n、m <= 1000 n、m <= 1000n メートル<=1 0 0 0

元の質問へのリンクを置くだけですSHOI 2002 SHOI2002S H O I 2 0 0 2スキー

メモリ検索、dp [i] [j] dp [i] [j]を検討d p [ i ] [ j ]は(i、j)(i、j)j 場所までの最長の道。

次に、各ポイントは一度だけdfsになるため、全体的な複雑度はO(n ∗ m)O(n * m)です。O nm ...

理解しにくいかもしれませんが、詳細についてはコードを参照してください...コードは非常に理解しやすいです。

Javaコード:

import java.io.*;
import java.util.*;


public class zbr01
{
    
    
	public static int [][]a=new int [1005][1005];
	public static int [][]dp=new int [1005][1005];
	public static int [][]k={
    
    {
    
    1,0},{
    
    0,1},{
    
    -1,0},{
    
    0,-1}};
	public static int n,m,ans;
	
	public static int dfs(int x,int y)
	{
    
    
		if(dp[x][y]!=0) return dp[x][y];
		for(int i=0;i<=3;i++)
		{
    
    
			int tx=x+k[i][0],ty=y+k[i][1];
			if(tx<1||ty<1||tx>n||ty>m||a[tx][ty]>=a[x][y]) continue;
			dp[x][y]=Math.max(dp[x][y],1+dfs(tx,ty));
		}
		return dp[x][y];
	}

	
	public static void main(String[] args)
	{
    
    
		Scanner S=new Scanner(System.in);
		n=S.nextInt(); m=S.nextInt();
		for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=S.nextInt();
		for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans=Math.max(ans,dfs(i,j));
		System.out.println(ans+1);
	}
}

T3

トピックの主なアイデア:固定形式、ルートノードのポイント加重バイナリツリーを前提として、下降のみ可能なxorパスの最大値を見つけます(xorパスの重みは、パス上のすべてのノードの排他的OR値です)。
n <= 1 e 5 n <= 1e5<=1 e 5

間違いは無数にあります...

(事前知識)
まず、「長さnのシーケンスで、2つの数値を選択してxorを最大化する」という質問を検討してください。
この問題は01trieで解決できます。Baiduで学習できます...

次に、この問題では、最初に前処理を検討します。w[x] w [x]w [ x ]は、xからルートノードへのパスのxor値です。次に、下りのみ可能なパスのxor値は、w [x] ^(w [すべての親ノード])の最大値に変換されます。

この部分は、次の疑似コードで表すことができます。

void dfs(int u)
{
    
    
	trie插入当前值;
	trie查询当前的xor最大值
	dfs(儿子节点);

	trie删除当前值;
}

対象の要件を完了することができます。

(弱い皿のブロガーの突然の精神遅滞のために...削除するトライを書く方法を忘れました...永続的な01トライを書いてください...最後に、デバッグできませんでした...

upd:
Tucao:どうしてみんなO(n 2)O(n ^ 2)O n2解雇されました...強く非難されました...どのようなデータですか?質問を書く際に作者は暴力を考慮していません...強く非難します!チェーンを作るだけで行き詰まる場合があります...このデータは修飾されていません

おすすめ

転載: blog.csdn.net/qq_38649940/article/details/108501724