1. 程式人生 > >2018 07 14 題解

2018 07 14 題解

ret dot eat vid obi logs 既然 scroll 中位數

2018 07 14


T1

Description
給出一個長度為 n 的序列 A,求這個序列的最長上升子序列的長度。

Hint
O(NlogN)模板題,不贅述了

Code

#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define
siz 100010
using namespace std; int n, m, len; int a[siz], dp[siz]; int sear(int dat) { int l = 0, r = len, mid, re; while(l <= r) { mid = (l + r) / 2; if(dp[mid] >= dat) r = mid - 1; else re = mid, l=mid + 1; } return re; } int main() { scanf
("%d",&n); for(int i=1; i<=n; ++i) scanf("%d",&a[i]); dp[0] = -2147483647; for(int i=1; i<=n; ++i) { if(a[i] > dp[len]) dp[++len] = a[i]; else { int j = sear(a[i]); dp[j + 1] = a[i]; } } printf("%d",len); return
0; }

T2

Description
給出一棵大小為 n 的樹,根為 1。點有點權。給出 m 個操作或詢問:

  1. 操作:節點 p 權值增加 w。
  2. 詢問:兩點(u,v)的路徑點權和。

Hint

Code


T3

Description
給出一個長度為 n 的排列 A,求這個排列有多少個長度為奇數的子串中位數是 mid。

Hint
首先知曉概念:子串是連續的
既然是長度為奇數的子串,中位數為mid,那一定是以mid為中位數的
又因為子串是連續的,所以我們只要以mid為界向兩邊延伸,如果大於mid的數和小於mid的數數量相等,這一串就符合題意.
這裏就有一個普通的優化,記大於mid的數為+1,小於mid的為-1,mid為0
向左累加,統計累計和為i的個數為L[i],同理向右,統計r[i]
答案即為$\sum {L[i]*R[-i]}$
註意 C++不能開負數組

Code

#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mid 1000000
#define siz 2000100
using namespace std;
int n, m, pos, cntl, cntr;
int a[siz], l[siz], r[siz];
long long ans;
int main() {

    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) {
        scanf("%d",&a[i]);
        if(a[i] < m) a[i] = -1;
        else if(a[i] == m) { pos = i; a[i] = 0;}
        else a[i] = 1;
    }
    for(int i=pos; i; i--) {
        cntl += a[i];
        l[cntl + mid] ++;
    }
    for(int i=pos; i<=n; ++i) {
        cntr += a[i];
        r[cntr + mid] ++;
    }
    for(int i=-(n-1); i<n; ++i) ans += (l[mid + i] * r[mid - i]);
    printf("%ld",ans);
    return 0;
}
?

2018 07 14 題解