1. 程式人生 > 實用技巧 >牛客小白月賽30

牛客小白月賽30

牛客小白月賽30

前言

這次比賽新生還有幾個打的不錯的,嗯至少明年能組一個隊能打,我這次感覺不在狀態
其實這次比賽的題沒有前幾次小白月賽難,AK的人也多,題目偏簡單,好了不說廢話了

黑白邊


解題思路:
這題是一道最小生成樹的題,prim最小生成樹會T,得用Kruskal並且是路徑壓縮優化的,因為出題人卡了時間
當然這題也能用並查集過,比較Kruskal的本質就是並查集嘛,(當然也要路徑壓縮優化)
鑑於是並查集/最小生成樹板子題,我不過多講解,儘量選取黑邊聯通就行
Code:

#include<bits/stdc++.h>
using namespace std;

const int N = 2e5+10;
int fa[N];
int n,m;
int cnt;

void init(int n) {//初始化
	for(int i = 1;i <= n; ++i) {
		fa[i] = i;
	}
}
int find(int x) {
	int t = x;
	while(t!=fa[t]) {
		t=fa[t];
	}
      //這裡就是路徑壓縮
	while(x!=fa[x]) {
		int temp = fa[x];
		fa[x] = t;
		x = temp;
	}
	return x;
}

int merge(int a,int b) {//將兩個點合併
	a = find(a),b = find(b);
	if(a != b) {
		fa[b] = a;
		cnt--;//表示的是剩餘的未聯通的點的個數
		return 1;
	}
	return 0;
}

struct Node {//邊
	int a,b,c;
}edge[N];

bool cmp(Node a,Node b) {//cmp排序函式
	return a.c<b.c;
}

int main()
{
	scanf("%d%d",&n,&m);
	init(n);
	cnt = n;
	for(int i = 0;i < m;++i) {
		scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].c);
	}
	bool fg = false;
	sort(edge,edge+m,cmp);
	int sum = 0;
	for(int i = 0;i < m; ++i) {
		int tt = merge(edge[i].a,edge[i].b);
		if(tt)
			sum+=edge[i].c;
		if(cnt == 1) {//如果全部聯通,那麼就直接退出迴圈
			fg = true;
			break;
		}
	}
	if(fg) {
		printf("%d\n",sum);
	}
	else
	puts("-1");
	
	return 0;
 } 

最好的寶石



解題思路:
很明顯是一道線段樹的題目,單點修改,區間查詢,屬於有手就行的題目(然鵝我沒手T^T,昨天寫了一手線段樹,寫炸了)
這題先挖坑,以後再填。先放上一個大佬(新都大三那位)的Code
Code:

#include <bits/stdc++.h>
#define reg register
#define ios ios::sync_with_stdio(false)
using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int eps = 1e-10;
const int maxn = 5e6 + 10;
const int mod = 1e9 + 7;

struct SegmentTree{
    int val[maxn ];
    int cnt[maxn];

    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid + 1, r
    
    void pushup(int rt)
    {
        int mx = 0,ct;
        if(val[rt << 1] > val[rt << 1 | 1]) {
            mx = val[rt << 1];
            ct = cnt[rt << 1];
        }
        else if(val[rt << 1] < val[rt << 1 | 1]){
            mx = val[rt << 1 | 1];
            ct = cnt[rt << 1 | 1];
        }
        else{
            mx = val[rt << 1 | 1];
            ct = cnt[rt << 1 | 1] + cnt[rt << 1];
        }
        val[rt] = mx;
        cnt[rt] = ct;
    }

    void build(int rt,int l,int r)
    {
        if(l == r){
            val[rt] = 0;
            cnt[rt] = 1;
            return ;
        }
        int mid = l + r >> 1;
        build(lson);
        build(rson);
    }

    void update(int rt,int l,int r,int p,int v)
    {
        if(l == r){
            val[rt] = v;
            return ;
        }    
        int mid = l + r >> 1;
        if(p <= mid) update(lson,p,v);
        else update(rson,p,v);
        pushup(rt);
    }

    int query(int rt, int l,int r,int ql,int qr)
    {
        if(ql <= l && r <= qr){
            return val[rt];
            
        }
        int res = 0;
        int mid = l + r >> 1;
        if(qr <= mid) res = max(res,query(lson,ql,qr));
        else if(ql > mid) res = max(res,query(rson,ql,qr));
        else res = max(res,max(query(lson,ql,mid),query(rson,mid + 1,qr)));
        return res;
    }

    int querycnt(int rt, int l,int r,int ql,int qr,int mx)
    {
        if(ql <= l && r <= qr){
            if(mx == val[rt]){
                return cnt[rt];
            }
            return 0;
        }
        int res = 0;
        int mid = l + r >> 1;
        if(qr <= mid) res += querycnt(lson,ql,qr,mx);
        else if(ql > mid) res += querycnt(rson,ql,qr,mx);
        else res = res + querycnt (lson,ql,mid,mx) + querycnt(rson,mid + 1,qr,mx);
        return res;
    }

}seg;

int main()
{
    int n,m;
    cin>>n>>m;
    seg.build(1,1,n);
    for(int i = 1;i <= n;++i){
        int tmp;
        scanf("%d",&tmp);
        seg.update(1,1,n,i,tmp);   
    }   
    while(m--){
        string s;
        int x,y;
        cin>>s>>x>>y;
        if(s == "Ask"){
            int mx = seg.query(1,1,n,x,y);
            int cnt = seg.querycnt(1,1,n,x,y,mx);
            printf("%d %d\n",mx,cnt);
        }
        else{
            seg.update(1,1,n,x,y);
        }
    }

    return 0;
}

滑板上樓梯


解題思路:
每次可以跳3階或者1階,因為要求跳的最小的次數那麼不難發現我們3 1 3 1的跳這樣以跳兩次為一個週期,最後剩餘的臺階
肯定是0或者1或者2或者3的,我們可以發現如果剩下的臺階數為1或者3,那麼直接跳一次就行,如果剩下的臺階數是2那麼,跳
兩次就行,如果剩下的臺階數是0,那麼就不用跳(因為資料有0的情況),我們可以先把週期數求出來,然後乘2就是前面跳的次數
然後我們在對剩下的臺階數進行判斷最後加起來就行
Code:

#include<bits/stdc++.h>
using namespace std;

long long n,m;

int main()
{
	long long sum = 0;
	cin>>n;
	long long k = n/4;
	n -= k * 4;
	sum += k*2;
	if(n== 1 || n == 3)
		sum += 1;
	else if(n == 2) 
		sum += 2;
	cout<<sum<<endl;
	return 0;
 } 

GCD


解題思路:
題目說在集合S種找到一個最小的k,任選S中k個元素作為子集T,子集T中存在兩不同元素x、y,使得\(GCD(x,y)>1\)
很顯然什麼時候才能滿足這個條件呢,就是看S元素中素數的個數,如果素數的個數佔了n-1個(n表示的是集合S中的元素)
那麼肯定沒有k能滿足條件的,因為無論怎麼選兩數,他們的GCD都是1,所以問題轉化為了找集合S的素數個數那麼可以
直接從1到n暴力判斷是否是素數,當然也可以用埃氏篩或者尤拉篩做(可以,但沒必要),最後找到了素數的個數k,因為元素1
不是素數,但是元素1必須要加入T集合中,並且還需要一個非素數的元素,所以最後\(ans=k+2\)
暴力判斷素數Code:

#include<bits/stdc++.h>
using namespace std;
bool isprime(int x) {//暴力判斷素數
      //注意我這裡,如果x=1的時候我判斷它是素數,這樣就能方便我們後續操作
	for(int i = 2;i *i <= x; ++i) {
		if(x%i==0)
		return false;
	}
	return true;
}
int main()
{
    int n;
    cin>>n;
    int sum = 0;
    int k ;
    for(int i = 1;i <= n; ++i) {//查詢素數的個數
    	if(isprime(i))
    	sum++;
	}
	if(sum == n) {//因為我們把1也認為是素數了
		k = -1;
	}
	else {
		k = sum+1;//加的這個1表示的是非素數的元素
	}
	cout<<k<<endl;
    return 0;
}

尤拉篩Code:

#include<bits/stdc++.h>
using namespace std;

const int N = 100005;
int prime[N];
bool vis[N];

int get_prime(int n) {
    memset(vis,true,sizeof vis);
    memset(prime,0,sizeof prime);
    vis[0] = vis[1] = false;
    for(int i = 2; i <= n; ++i) {
        if (vis[i]) {
            prime[++prime[0]] = i;
        }
        for(int j = 1;j <= prime[0] && i*prime[j] <= n; ++j) {
            vis[i * prime[j]] = false;
            if (i % prime[j] == 0)                
                break;
        }    
    }
    return prime[0];//返回的是素數的個數
}
int main()
{
    int n;
    cin>>n;
    int k = get_prime(n);
    if(k == n-1)//判斷素數的個數是否是n-1個
    	cout<<-1<<endl;
	else 
	cout<<k+2<<endl;//素數的個數+1元素+非素數元素
    return 0;
}

牛牛的加法


解題思路:
題目描述有問題,至少說有歧義吧,我以為不進位是說的是最大位不進位,然鵝出題人想表達的意思是每個位置加和都不進位
那這樣的話就更簡單了,我們直接從後往前加和然後對當前的數進行取餘10,最後在再從前往後輸出,注意這裡有個坑點
不能要字首0,並且如果全為0的情況,直接輸出0
Code:

#include<bits/stdc++.h>
using namespace std;
const int N = 200010;
int c[N];

void slove(string a, string b) {//a的長度 < b
	int len1 = a.size();
	int len2 = b.size();
      //把元素往後移一位(開始我以為要進位,所以這樣操作的,這個可以不用)
	for(int i = len1;i > 0; --i)	a[i] = a[i-1];
	for(int i = len2;i > 0; --i)	b[i] = b[i-1];
	int i = len2;
      //然後從後往前開始加和並且不能進位
	for(int j = len1;j > 0; --j,--i) {
			int k = a[j] -'0'  +  b[i] - '0';
			c[i] += k;		
			c[i] %= 10;//直接對10取模,不用進位
		}
		while(i) {//把b剩下的值放進c中
			c[i] += b[i]-'0';
			i--;
		}
	i = 1;
	bool fg = false;//是否是全為0
	while(c[i] == 0 && i <= len2) i++;
	for(;i <= max(len1,len2);++i) {
		cout<<c[i];
		fg = true;//如果有不為0的輸出,則將fg改變狀態
	}
	if(!fg)//如果全為0,則直接輸出0
	cout<<0;
	cout<<"\n";
}
int main()
{
	string a,b;
	cin>>a>>b;
	int len1 = a.size();
	int len2 = b.size();
	if(len1 < len2)
		slove(a,b);
	else
		slove(b,a);
	return 0;
 } 

石子合併


解題思路:
相鄰的兩堆石子,取走價值最小的那一堆,得到的價值是兩堆之和,不難發現,我們找到所有石子中價值最大的那一堆
然後讓該石子和其他所有石子進行取的操作得到的價值是最大的,因為我們每次取走石子的到的價值是取走石子的價值
加上最大石子的價值,如果我們不和最大石子進行取操作的話,得到的價值肯定是小於和最大石子進行取操作的值
所以問題轉化為了求所有石子中價值最大的k,然後把其他石子的價值加起來sum,最後的到的總價值是\(sum+k\time(n-1)\)
Code:

#include<bits/stdc++.h>
using namespace std;

const int N =200005;
int a[N],n,max_;//max_表示的是最大元素的值

int main()
{
    long long sum=0;
    scanf("%d",&n);
    for(int i = 0;i < n; ++i)
    {
        scanf("%d",&a[i]);
        max_ = max(max_,a[i]);
        sum += a[i];
    }
    if(n>=2)
    	printf("%lld",(n-2) * max_ + sum);//這裡減去2是因為上面迴圈的時候已經加過一次max_
                                          //也就是說最大值已經加在了sum裡面
    else //注意n=1的情況直接輸出0
    	puts("0");
 
    return 0;
 }

滑板比賽



解題思路:
牛牛有n個動作每個動作的華麗值為a[i],牛妹有m個動作,每個動作的華麗值為b[i],要想牛牛贏得次數儘可能多,因為每
個動作只能比較一次那麼我們就要讓牛牛華麗值最高的動作依次和牛妹的華麗值最高的動作依次比較,然後判斷牛牛能贏多少場,
時間複雜度為\(O(M)\),我們設一個i指標(陣列的位置)表示牛牛當前的華麗值的位置,j表示牛妹華麗值的位置,我們遍歷牛妹的華麗值
如果牛牛華麗值大於牛妹的華麗值,那麼讓牛牛的i往後移一位,每次比較完牛妹的指標往後移一位,看程式碼可能要清楚點
Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 200005;
bool cmp(int a,int b) {
	return a>b;
}
int a[N],b[N];

int main()
{
	ios::sync_with_stdio(false);
	int n,m;
	cin>>n>>m;
	for(int i = 0;i < n; ++i) {
		cin>>a[i];
	}
	for(int i = 0;i < m; ++i) {
		cin>>b[i];
	}
	sort(a,a+n,cmp);//對牛牛的華麗值進行排序
	sort(b,b+m,cmp);//對牛妹的華麗值進行排序
	int ans = 0;//牛牛勝利的次數
        //為什麼要遍歷牛妹的華麗值呢,因為每個動作只能比較一次
	for(int i = 0,j = 0;i < m; ++i) {//j表示的是牛牛的第(j+1)大的華麗值的位置
		if(a[j] > b[i]) {//如果牛牛的華麗值大於牛妹的華麗值那麼讓牛牛的位置往後移
			j++;
			ans++;//勝利次數+1
		}
	}
	cout<<ans;
	return 0;
 } 

第 k 小



解題思路:
要找到第k小的數,並且可以往數組裡面新增元素,那麼我們可以維護一個大頂堆的優先佇列,讓佇列的元素個數一直保持 <= k個
如果佇列元素的個數小於k那麼輸出-1,否則輸出佇列頂端的元素,每次插入元素的時候如果插入後元素個數大於k那麼就pop
時間複雜度為\(n(logn)\)
Code:

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;

const int N = 200005;
int n,m,k;
int a[N];
priority_queue<int> que;

int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i = 1;i <= n; ++i) {
		scanf("%d",&a[i]);
	}
	sort(a+1,a+n+1);

	for(int i = 1;i <= n && i <= k; ++i) {//把前k小的元素放進佇列
		que.push(a[i]);
	}
	
	int loc = min(n,k);
	while(m--) {
		int x,y;
		scanf("%d",&x);
		if(x == 1) {//插入元素
			scanf("%d",&x);
			que.push(x);
			loc++;
			if(loc > k) {//當佇列元素中個數大於k
				loc--;
				que.pop();
			}
		}
		else {
			if(loc == k)//如果佇列元素個數剛好等於k,那麼輸出隊首元素
				printf("%d\n",que.top());
			else//否則就沒有第k小元素
				printf("-1\n");
		}
	}
	return 0;
}

區間異或



解題思路:
看了下資料n=3e3的,我們可以通過一個\(O(N^2)\)的預處理,求得每個長度的異或最大值,對於每次查詢只需要\(O(N)\)
查詢時間就夠了,具體操作看程式碼,總時間複雜度為\(O(N^2+M\timesN)\)
Code:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;

const int N = 3005;
int n,m;
int a[N];
vector<int> V;

int main()
{
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n; ++i) scanf("%d",&a[i]);
	
	for(int i = 1;i <= n; ++i) {
		int ans = 0, mx = 0;//這裡的mx表示的是長度為i的時候的區間最大異或值
		for(int j = 1; j <= n; ++j) {
			ans ^= a[j];
			if(j > i) ans ^= a[j - i];//兩個相同的數進行異或操作為0
                                                  //這樣就讓我們把每次異或的區間長度控制為i
			mx = max(mx,ans);
		}
		V.push_back(mx);
	}
	int x;
	while(m--) {
		scanf("%d",&x);
		int ans = -1;//我先讓位置為-1,表示查不到的情況
		for(int i = 0;i < V.size(); ++i) {//從小到大查詢
			if(V[i] >= x) {//查到第一個大於等於x的位置直接儲存位置,然後跳出迴圈
				ans = i+1;
				break;
			}
		}
		printf("%d\n",ans);//輸出查詢到的位置
	}
	return 0;
}

小遊戲



解題思路:
題目說拿走x之後x-1和x+1變得不能拿,那麼我們就可以將這個問題轉化為動態規劃,第一眼我看成了01揹包
其實這是一個線性dp,dp[i]表示的是直到第i個數取走的最大分數,那麼就能列出狀態轉移方程如下

\[ dp[i] = \begin{cases} 0 & \text{i == 0} \\ cnt[i] & \text{i == 1} \\ max(dp[i-1],dp[i-2]+i*cnt[i]) & \text{i >= 2} \end{cases} \]

Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long 

const int N = 200005;
ll dp[N];
int cnt[N];

int main()
{
	int n,x;
	scanf("%d",&n);
	for(int i = 0;i < n; ++i) {
		scanf("%d",&x);
		cnt[x]++;
	}
	dp[1] = 1LL * cnt[1];
	for(int i = 2;i <= 200000; ++i) {
			dp[i] = max(dp[i-1],dp[i-2] + 1LL * cnt[i] * i);
	}
	cout<<dp[200000]<<endl;
	return 0;
}

總結

題目總體偏簡單,但是也不是語法題,比較適合才入門的新生,當然我這次做的挺爛的,有些題還是要仔細想想,不要直接莽
平時的練習倒無所謂,真正比賽的時候有罰時,還是要提高一下寫題的準確性

/*
                                                                                                                             .
                                                                                                      `;|$&@&$%%%|||%%$&@&%' .
    '$$%|!!!;;;!!!||%$@@&%;'                                                                  .:%&&%!:::::::::::::::::::::|!..
   .||:::::::::::::::::::::::;|$@$!`                                                     `|&$!::::::::::::::::::::::::::::!|'.
   ;%:::::::::::::::::::::::::::::::;|&&!`                                          `|&$!:::::::::::::::::::::::::::::::::!%:.
  `||:::::::::::::::::::::::::::::::::::::!$&|'                                 '%&|::::::::::::::::::::::::::::::::::::::;%;.
  :%;:::::::::::::::::::::::::::::::::::::::::!$@&;.                        '%@%;::::::::::::::::::::::::::::::::::::::::::%!`
  !%:::::::::::::::::::::::::::::::::::::::::::::!%&@&!.                .!&@$|:::::::::::::::::::::::::::::::::::::::::::::%!`
 .||:::::::::::::::::::::::::::::::::::::::::::::::;|$$&@&;.'%@@@@$!``%@&$%!:::::::::::::::::::::::::::::::::::::::::::::::|!'
 `|!:::::::::::::::::::::::::::::::::::::::::::::::;!|%$$&@$;:::::;|&@&$%!:::::::::::::::::::::::::::::::::::::::::::::::::||'
 :|;::::::::::::::::::::::::::::::::::::::::::;%&@@@@$%|!!;:::::;!|%&@##@&$$%!:::::::::::::::::::::::::::::::::::::::::::::||:
 :%;:::::::::::::::::::::::::::::::::::!%&@$|;'````.```..```...```..``..```:|&@@|;:::::::::::::::::::::::::::::::::::::::::||:
 :%;::::::::::::::::::::::::::::::!$&|:`.`..................................`````;$&|;:::::::::::::::::::::::::::::::::::::||'
 :%;::::::::::::::::::::::::::|&$:`.........``.................................`.````;$$!::::::::::::::::::::::::::::::::::||'
 '|!::::::::::::::::::::::;%$!`.`````.................................................``:%$!:::::::::::::::::::::::::::::::%!`
 `||:::::::::::::::::::;|$!`..```.......................................................```;$%;::::::::::::::::::::::::::::%!`
  !|:::::::::::::::::!$%'`.............................................................``..``'%&|;::::::::::::::::::::::::;%;.
  ;%;::::::::::::::!$!```..............................................................`...````'%@$|;:::::::::::::::::::::!%:.
  '|!::::::::::::!$!`.`....................................................................``````'%&$$|:::::::::::::::::::||`.
  .!|::::::::::;%!   ..........................................................................````;&&$$%;::::::::::::::::%! .
   :%;::::::::%%`          ...````````.........`.............................................```.``.'%&$%$%!:::::::::::::;%; .
   .!|::::::!%;     .               .....```..```````````.``........................................``!&$$%%%!:::::::::::!|' .
    :|;::::|%'    ..                                   ....``..........................................:$&$$$$%;:::::::::%!  .
     !%::;%|'``.....                      .....```..................................................````:$&$$%$$|;::::::!%'  .
     '|!;%|`.......`.`.........````````..`.......```...........`````.................................````:%&$$$$$%!:::::%!   .
      ;$$|`...`':'..`.`````....`````|!`````...................```.````.................`....````..........:$&$%%%%$|:::!|'   .
      .||``.``'|!```...........``.`:|;````;!'.``..............```.::```...................`'!:.`.......`..`;$&%%%$$$|;;%;    .
      ;|'...``!|'``.`````..........;|:``.:$|`...................``;|:......................'|!```.......``.`!&$%%$%$$%$!     .
     :|:.``..'|!.``..``````......``!%:.`:%&|```...............```'!%|:````.`....```.......`'|!..............'%&$%$$$$@|.     .
    `|;..````:|:..``;|'.```.......`;%;`:%&#!```..................:|$%:``'|!``````.......```'|!``..........```;$&$%$$@|.      .
    !|``...``;|:`..'%%'..```..```:%&&!'!&&$!`.```.``..........```;%&%```|&;``:%!```....```.'|;.``...`.``..`.``|&$$$@|        .
   :|:.``````;|:``;$@%:````````'|$;:%%;%&!||`....`''........``..:|$&!``!&&&;``|#$'``....``.:|;`````..`!|'``..`:$&&&;         .
   !!````||``:|;`!$@#$:`....``:%|:::;$$$%`;|'....`:'...........`;%&%:`!$;:!&%'!$$&!`...```.;|'`..```..;$;....``|#&$;         .
  :|:..`:%;```||;%&@@&;``````;$!:'` .;&@; `|;````.::`........``:|%&!`|$;:` `|$$|;%@@|'....`||`````..``;$|'..```;%!||.        .
  |!.```!|'```;$%$&$&&|'`'|$$&|:'.    `'.  !|`..`.';'.........'!%&%;|%:'.  '%@#&: `|&%:```:|;`````````;$%:```..'||!%:        .
 '|:```'%!`..``!&&&%$&%:`.`:%%|$@&!`       `|!```.'!;`....``.`;|$&%%%:;|&$:.        :&@%;`!|`.`````..`;$$;::`.``!%;%!        .
 !|`..`!$;..`..:&@$|%&&!'`'%%:`    .;$@$:.  :|:...`;|;`.`.`..:|%&@&&%:.             .|&$&@$;.....`````;$$!!!'..`;%;!|`       .
.|!`..:$%'```.`;||||%&@$;`!%;`            '!!|%:.``;|!'```..'!%&#&;'.                !&;````.......```;$$||!'..`:%!;%;       .
`|;..`!&|````.:!||||%&&&%|%!'.                :%;``;||;````'!|$@%:`   `:|$@#####%`   :$!``..``........;$%|||:`.`'||:%!       .
'|:..:|&|`''``:|||||%&%'%@!.;@@@#####@&$|!'.   `|!';|%!'```;%$&||&&@@@@@&&&&&@#|     :$|'``.......``.`!$%|||;```'||:||`      .
:|'.`;%&!.:;``;|||||%&%`   `|@&&&&&&&&&&@&'      ;&$%|!'.`;|$&;.!@&&&&&&&&&&&@#|.    '%|'``.......````!&%||%!`.`'||:;%:      .
:|'.`;%$!`;!'`;|||||%&|.   '%|;%&&&&&&&&@$`        !&$|:`;%&%`  !%`.!&&&&&$$$$@%`    '%|'``.```...````|&%|||!'.`'||:;%;      .
:|'.'!%$!`;|:`;|||||%&|.   :;  `|%|%%|||$|.          ;$|;$&;    ::  `!%%|%||||&%`    '%%'``.```.''```'%$%|||!'.`'||::%!      .
'|:`:|%$!`;|;`;|||||%&!    ;$||||%|%%|||&;             .'`      '%|||||%%%||||&%.    '%|'``...`.':`.`:%$|||||:..:|!::||.     .
`!;.:|%&!`;||:;||||%$&;    ;$||||||||||$%'                      .|$|||%%%%|||%@|     '$|'.`..`.`:!:``!$%|||||:``;$!::!|`     .
.||`:|%&|`;||;;||||%&%`    '%%||%%%||%%&!                        :%|||%|||%||$$'     :$!`..`````;|:``|&||||||:.`|&!::!|'     .
`$%''!|&%';||||||||%&!      !$|'.```:|&%.                         ;$%'     :$&:      ;$!`......:||:`:%$||||||:.:$$;::!%:     .
'$&;'!|$$::|||||||%&%`      .|&:   .!@|.                           .|&|`.`;&$'       !&;`....``;||;`!$%||||||:`!&%;::!%:     .
:%$|';|%&!'!||||||%&%'  ......`!@##@!.                                '|&&|'.`....  .|$:...```:|||;'%$|||||%$;:$&|;::!%:     .
;%;%|;||&$::||||||%$$:..``````````.      ;;                            ...````````..`|%'....`'!|||:;$%||||%$$!|&$|;::!%:     .
;%;|$|!|%&|`;%|||||%&!..`````````...     .|#################@@$;.      ..``````````.:$|'```.`;||||;%$||%%%%&$%&$%|:::!|'     .
:|;;%&$||%$;:$$||||%&%'..````````..       '$##&;``````````````:$&'      ..```````.. ;$!`````:||||!%$%|$&$|$#@&$%%!:::||`     .
'|!:|$@&%%$$;;&$||||%&|. ........         :@$:`````````````````|$:         ......   !$:.```'!%%||%$%|%&@$$##@$%$%;:::|!.     .
 !%:!%$@&%%@@!%@%||||%&%`                 '$!``````````````````|%`                 `%%'``.'!%&&%$@$%%&#&@##@$%%$|;:::%!      .
 `%&&@$|!$&&$$#&&$%|||%&#%`               .|$:````````````````:%:                  :$!````;|$&%%@&%$&%&@; `|@@&%;:::;|:      .
          '&&';!:%&%|||$&$$@$:             .|&;``````````````;%:               .;&@@$:`.`;|$@$$@&$&|'%%.       .:|$&@|.      .
            `'    ;&$||%&&%||%&@|`           `%&!``````````:%!.            `!&@$%%%&|`.`:|$@&&#@&$:                          .
                    !&$%%&#@%|||%$&@%'          .';;'`...''.          `!&#&%|||||%$$;`.:%&#@@#@@!.                           .
         .;%&&$$&!    :&&$&%|@$%%&@$%%$@#@|:.                 .`;%&@&@$:``:%&$%%%&@%``:%@#@||#|!$!'';|$@!                    .
          ;&%:```'|$:    :$#%.`|@@@%!&#&;```':;|&#@@@@@@@&$%|!;:::|&!.       '$%``|;`;&|. .;!|$;``'!%&@;                     .
           .%&$$$%|;;$%`       `%$!':%%`         `|&|::::::::::;$%`          ;&$!|%|&|.   `%@$$&&&&@#%`                      .
             `;;;;;;;;;;`     ||      '$;           :$|:::::'!&!           `%|.  !|` !|.           .::.                      .
              
             */