板刷计划:ARC071

前言:又只写出一题,感觉要提前退役了呢

A.水

B.二维计数题

题目大意:

二维平面上给你由 n 条 y = y i y = y_i y=yi 的直线和 m条 x = x j x = x_j x=xj的直线.问你所有构成的子矩阵的面积之和.( n , m ≤ 1 e 5 n,m \leq 1e5 n,m1e5)

题目思路:

之前做过单纯的求子矩阵的个数之和.这次变成求子矩阵的面积之和.就没推出来了…很烦.所以让我们严格的来推导一波吧.

1.朴素计算式: a n s = ∑ 1 ≤ i < j ≤ n ∑ 1 ≤ k < l ≤ m ( x j − x i ) ∗ ( y l − y k ) ans = \sum_{1 \leq i < j \leq n}\sum_{1 \leq k < l \leq m} (x_j-x_i)* (y_l-y_k) ans=1i<jn1k<lm(xjxi)(ylyk)

复杂度: O ( n 4 ) O(n^4) O(n4)

2.观察到两项独立,则有: a n s = ∑ 1 ≤ i < j ≤ n ( x j − x i ) ∗ ∑ 1 ≤ k < l ≤ m ( y l − y k ) ans = \sum_{1 \leq i < j \leq n} (x_j-x_i)* \sum_{1 \leq k < l \leq m} (y_l-y_k) ans=1i<jn(xjxi)1k<lm(ylyk)

复杂度: O ( n 2 ) O(n^2) O(n2)

考虑两项的意义: ∑ 1 ≤ i < j ≤ n ( x j − x i ) \sum_{1 \leq i < j \leq n} (x_j-x_i) 1i<jn(xjxi)就是在数组 x x x上求解所有连续子段和.

那么考虑每一个相邻的段 x i − x i + 1 x_i-x_{i + 1} xixi+1它对答案的贡献为: x i x_i xi左侧的点个数乘上 x i + 1 x_{i+1} xi+1右侧的点个数.

所以上述式子转化为: ∑ i = 1 n − 1 ( x i − x i + 1 ) ∗ i ∗ ( n − i ) \sum_{i=1}^{n-1} (x_i-x_{i+1}) * i*(n - i) i=1n1(xixi+1)i(ni) ,对y求解一样的方法.

复杂度为: O ( n ) O(n) O(n)

后话:其实它的实际含义也很好理解:一个矩阵其实就是X方向上确定两个点 + Y方向上确定两个点构成的四元组.

C.究极思维题

题目大意:

有两个只含AB的字符串S,T( ∣ S ∣ , ∣ T ∣ ≤ 1 e 5 |S|,|T| \leq 1e5 S,T1e5).你有两种操作:1.将A转换为BB 或 将B转化为AA. 2.删除AAA/BBB.
现在有Q( Q ≤ 1 e 5 Q \leq 1e5 Q1e5)次询问,每次询问你S和T的一段子字符串.问你这两个子字符串是否能够通过任意次上述操作使其相等.

题目思路:

朴素思路:
思考操作的一般性质:可逆性和相邻交换性

这两个性质很容易看出来: AB <-> AAA <-> BA.

其实根据题目也是要往这方面想.因为Q这么大,我们肯定是 O ( 1 ) O(1) O(1)判定.

观察出这两个特性之后,我们可以知道其实只需要关注两字符串中的A,B个数即可.

又发现一性质:可以凭空增加一个 ‘AB’. 即: B -> AA -> ABB .相当于A,B各增加一个.

所以我们可以先对一种字符 A/B 将他们调整到一致.再讨论另一个.

然而另一个字符只有相差 3的倍数时,才能调整到一致.

所以维护前缀和.差分判断一下即可.

巧妙思路:Hash
将A 看做1, B 看做 2.
则:
A -> BB 等价于 1 -> 4
B -> AA 等价于 2 -> 2
AAA -> 空 等价于 3 -> 0
BBB -> 空 等价于 6 -> 0.

所以容易发现: 这四种操作都无法改变 字符串数值和 在 模3 意义下的 值.且可以构造出无限大的数值和 并且根据上一个方法得到的 可逆性 和 相邻交换性 .就可直接判断 两子串数值和 模3 意义下 的值是否相等.

D.思维,dp

题目大意:

一个无限长的序列,满足以下两个规则:

1. [ n , + ∞ ) [n,+\infty) [n,+)范围内的数全等
2.对于一个数 a i a_i ai, [ i + 1 , i + a i ] [i+1,i+a_i] [i+1,i+ai]范围内的数全等.

现在问你长度为n( n ≤ 1 e 6 n\leq1e6 n1e6)能够产生多少个不同的序列.

题目思路:

不难发现本题关键点:当存在两个相邻的非1项时,从这两项开始后面的值就已经确定了.

形如: [ a , b , b , b . . . , b ] [a,b,b,b...,b] [a,b,b,b...,b]

不难利用动态规划,从后往前dp.

1.当第i位填 x = 1 x=1 x=1时, f i ← f i + 1 f_i \leftarrow f_{i+1} fifi+1

2.当第i位填 x ∈ [ 2 , n − i ] x \in [2,n-i] x[2,ni]时, f i ← ∑ k = i + 3 n f k f_i \leftarrow \sum_{k = i + 3}^{n}f_k fik=i+3nfk

3.当第i位填 x ∈ [ n − i + 1 , n ] x \in [n-i+1,n] x[ni+1,n]时, f i ← i f_i \leftarrow i fii

4当第i位和第i+1位填非1数时, f i ← ( n − 1 ) 2 f_i \leftarrow (n - 1)^2 fi(n1)2

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
using namespace std;
const int maxn = 1e6 + 4;
const int mod = 1e9 + 7;
ll dp[maxn] , aft[maxn];
int main()
{
    
    
    ios::sync_with_stdio(false);
    ll n; cin >> n;
    if (n == 1){
    
    
        cout << 1 << endl;
        return 0;
    }
    dp[n] = n;
    dp[n - 1] = n * n % mod;
    aft[n + 1] = 1;
    aft[n] = dp[n] + aft[n + 1];
    aft[n - 1] = (aft[n] + dp[n - 1]) % mod;
    //aft[n + 1] = 1;
    for (ll i = n - 2 ; i >= 1 ; i--){
    
    
        // 填x = [2,n - i],后面跟x个1
        dp[i] = (dp[i] + aft[i + 3]) % mod;
        // 填写一个1
        dp[i] = (dp[i] + dp[i + 1]) % mod;
        // 填x = [n - i + 1 , n], 后面跟 n - i 个1
        dp[i] = (dp[i] + i) % mod;
        // 前后两项都填非1数
        dp[i] = (dp[i] + 1ll*(n - 1ll)*(n - 1ll)%mod) % mod;
        aft[i] = (aft[i + 1] + dp[i]) % mod;
    }
    cout << dp[1] << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35577488/article/details/108941113
071
arc