标签:oiv ida vld tps sign zid 不能 mdx zcm
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;
}
Description
给出一棵大小为 n 的树,根为 1。点有点权。给出 m 个操作或询问:
Hint
Code
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;
}
标签:oiv ida vld tps sign zid 不能 mdx zcm
原文地址:https://www.cnblogs.com/LonelyRyan/p/9315913.html