day1

赵梓烨發表於2024-10-07

day 1

雷暴 (storm)

題目要求計算覆蓋所有相同顏色格子的最小正方形的面積。


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

int n, m, k;
int a[1005][1005];

struct node{
	int x, y;
}f[100005], g[100005];

int main()
{
	freopen("storm.in", "r", stdin);
	freopen("storm.out", "w", stdout);
	ios :: sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> k;
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++)
			cin >> a[i][j];
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++)
		{
			if(f[a[i][j]].x == 0 && f[a[i][j]].y == 0) 
			{
				f[a[i][j]].x = i;
				f[a[i][j]].y = j;
			}
			else 
			{
				f[a[i][j]].x = min(f[a[i][j]].x, i);
				f[a[i][j]].y = min(f[a[i][j]].y, j);
			}
		}
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++)
		{
			if(g[a[i][j]].x == 0 && g[a[i][j]].y == 0) 
			{
				g[a[i][j]].x = i;
				g[a[i][j]].y = j;
			}
			else 
			{
				g[a[i][j]].x = max(g[a[i][j]].x, i);
				g[a[i][j]].y = max(g[a[i][j]].y, j);
			}
		}
	for(int i = 1;i <= k;i++)
	{
		int t = abs(max(g[i].x - f[i].x, g[i].y - f[i].y)) + 1;
		cout<<t * t<<"\n";
	}
	return 0;
}

神力

小z初始在0號位置,每次都會向左或向右走一個單位座標,他的行走軌跡可以看作一個長度為n的序列\(a_i\)保證\(abs\)|\(a_i\)| \(=1\)

因為神力的存在,所以小 Z 有\(\frac{p}{100}\)的機率可能在第 i 個時刻突然不想移動了,即不
進行這個時刻的移動操作

題目需要計算小Z經過各個位置的機率,並返回對應的結果。

樣例

輸入

5 83

1 -1 -1 1 1

輸出

0 0 0 710859005 390982003 1 135049706 506522154 13802205 0 0

soluton

我們考慮從後往前,令\(f_i,_j\)考慮了後\(i\)步操作,當前位置為\(j\)的機率。

每次只要將\(f_i,0\)設為1即可

code

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

const int N = 5005, MOD = 1e9 + 7;

int qpow(int x, int y)
{
   int cnt = 1;
   for(; y; y >>= 1)
   {
   	if(y & 1) cnt = cnt * x % MOD;
   	x = x * x % MOD;
   }
   return cnt;
}

int n, p, a[N], dp[N][N * 2], ans; 

signed main()
{
   cin >> n >> p;
   p = p * qpow(100, MOD - 2) % MOD;
   int ip = (1 - p + MOD) % MOD;
   for(int i = 1;i <= n;i++)
   	cin >> a[i];
   dp[0][n] = 1;
   for(int i = 1;i <= n;i++)
   {
   	for(int j = n - i + 1;j <= n + i - 1;j++)
   	{
   		dp[i][j] = (dp[i][j] + p * dp[i - 1][j]) % MOD;
   		dp[i][j + a[n - i + 1]] = (dp[i][j + a[n - i + 1]] + ip * dp[i - 1][j]) % MOD;
   	}
   	dp[i][n] = 1;
   }
   for(int i = 0;i <= 2 * n;i++)
   	cout<<dp[n][i]<<" ";
   cout<<"\n";
   return 0;
} 

之緣千里(fate)##

緣分化成了一個長度為 2n 的合法括號串,這 2n 個字元(( 或 ))代表了 2n 個靈
魂,分成 n 組命運,每組恰好包含 2 個靈魂。
對於每組靈魂,由於它們相互連線,所以它們代表的字元需要相同。

現在,給定這 2n 個靈魂所在的命運組,求是否存在這樣的合法括號串,如果存在,
則構造一組字典序最小的解,否則輸出 😦 表示不存在。

特別地,如果你構造的解不滿足字典序最小,但也是合法括號串,你可以獲得這個測試點 50% 的分數。

樣例

輸入

4

1 1 3 2 2 4 4 3

輸出

(()(()))

solution

引理

一個長度為\(2n\)的括號串合法,當且僅當所有左括號的位置能被\(1, 3, 5, 7...,2n - 1\)偏序

證明

和括號字首函式\(>0\)是等價的

演算法

\(nxt_i\)表示\(a_i\)右側對應的位置

於是我們可以看作是左括號位置和\(1, 3, 5, 7...,2n - 1\)的位置匹配。

時間複雜度$O(n \(log\) n)

code

#include <bits/stdc++.h>
using namespace std;
#define F(i, j, k) for(int i = j;i <= k;i++>)
const intn N = 2e6 + 10;
int n, p[N], nxt[N], h[N], ans[N];
set<int> st;
int main()
{
    cin >> n;
    F(i, 1, n * 2) 
    {
        cin >> p[i];
        nxt[h[p[i]]] = i;
        h[p[i]] = i;
    }
    F(i, 1, n)
        st.insert(i * 2 - 1);
    F(i, 1, n * 2)
        if(nxt[i]){
            if(st.size() && st.rbegin() >= nxt[i]){
                st.erase(st.lower_bound(nxt[i]));
                auto p = st.lower_bound(i);
                if(p == st.end()) return puts(":("), 0;
                st.erase(p), ans[i] = ans[nxt[i]] = 1;
            }
        }
    if(st.size()) return puts(":("), 0;
    F(i, 1, n * 2) cout<<(ans[i] ? '(' : ')');
    return 0;
}

怒氣沖天(rectangle)

給定\(n\)個矩形,求有幾個三元組\((i, j, k)\), 滿足\((i, j), (j, k), (i, k)\)沒有交

solution

矩形滿足以下四種情況
img


於是,我們只需要求出\(deg_i\)表示第\(i\)個矩陣有交的數量

程式碼就不貼了,掃描線和線段樹我也不會。