题目:
[LINK](http://www.lightoj.com/volume_showproblem.php?problem=1402)
给你一些点(SRT, R);
按照SRT排序, 然后再坐标系中画出这些点, 连成一条线。
线会有峰点(peak),一个点是峰点, 相邻两个点的 R 值都比它小 或 大。
然后WARush 要丧病的忽略一些点,(忽略第X点后,第 X 后面的点会前移! )
会形成新的线。 然后题目要求输出所有线条中刚好有 K 个峰点的**不同线条**的数量。
分析:
题目中 单个点 和 没有点 都算一种情况。
先把所有点排序, 然后依次画图, 统计线条数。
对于 第 i 个点画图时 :
枚举 K 值
当K == 0时, 我们可以得出:
上升线条 Up = [比 Ri 低的点的数目] + [总结点数] + [上升线条尾端点值比 Ri 低的数]
下降线条 Down 同理。
故Dp[k] = Up + Down + 节点node 数。
当 K > 0 时。 :
上升线条 Up(k) = [上升线条 Up(k) 中尾端点比 Ri 小的线条数] + \
[ 下降线条 Down(k-1) 中尾端点比 Ri 小的线条数].
下降线条 Down(k) 同理。
怎么求这些值? 用树状数组维护就好了。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned int U32;
const int maxn = 10000 + 131;
inline int lowbit(int x) {
return x & (-x);
}
struct BIT {
U32 Num[maxn];
int N;
void INIT(int n) {
N = n;
memset(Num, 0, sizeof(Num));
}
void Add(int x, U32 val) {
while(x <= N) {
Num[x] += val;
x += lowbit(x);
}
}
U32 Sum(int x) {
U32 ret = 0;
while(x > 0) {
ret += Num[x];
x -= lowbit(x);
}
return ret;
}
U32 Sec(int L, int R) {
return Sum(R) - Sum(L-1);
}
};
struct State {
BIT Up, Down, Node;
void INIT(int n) {
Up.INIT(n);
Down.INIT(n);
Node.INIT(n);
}
};
struct Data {
int s, r;
bool operator < (const Data& a) const {
return this->s < a.s;
}
};
Data node[maxn];
State Dp[60];
int R_n[maxn];
int main() {
int T;
scanf("%d",&T);
for(int kase = 1; kase <= T; ++kase) {
int n, K;
scanf("%d%d",&n, &K);
for(int i = 0; i < n; ++i) {
scanf("%d%d",&node[i].s, &node[i].r);
R_n[i] = node[i].r;
}
sort(R_n, R_n+n);
int C = unique(R_n, R_n+n) - R_n;
int Max = -1;
for(int i = 0; i < n; ++i) {
node[i].r = lower_bound(R_n, R_n+C, node[i].r)-R_n+1;
Max = max(Max, node[i].r);
}
sort(node, node+n);
for(int i = 0; i <= K; ++i) Dp[i].INIT(Max);
for(int i = 0; i < n; ++i) {
int h = node[i].r;
for(int k = 0; k <= K; ++k) {
U32 Sum_Up = -Dp[k].Up.Sec(h,h);
U32 Sum_down = -Dp[k].Down.Sec(h,h);
U32 Sum_node = -Dp[k].Node.Sec(h,h);
Sum_Up += Dp[k].Up.Sum(h-1) + Dp[k].Node.Sum(h-1);
Sum_down += Dp[k].Down.Sec(h+1, Max) + Dp[k].Node.Sec(h+1,Max);
if(k == 0) Sum_node++;
else {
Sum_Up += Dp[k-1].Down.Sum(h-1);
Sum_down += Dp[k-1].Up.Sec(h+1, Max);
}
if(Sum_Up) Dp[k].Up.Add(h, Sum_Up);
if(Sum_down) Dp[k].Down.Add(h, Sum_down);
if(Sum_node) Dp[k].Node.Add(h, Sum_node);
}
}
U32 Ans = 0;
Ans = Dp[K].Down.Sum(Max) + Dp[K].Up.Sum(Max) + Dp[K].Node.Sum(Max);
if(K == 0) Ans ++;
printf("Case %d: %u\n",kase, Ans);
}
return 0;
}