题解 P1311 【选择客栈】
题目大意
给定
对于任意的两个数
求使得
题解
显然的一道
设
60分的话是挺好想的。
我们考虑
for(int i = 1 ; i <= n ; ++ i) {
for(int j = 1 ; j < i ; ++ j) {
if(a[j] == a[i] && min[i,j] <= p) f[i] ++;
}
}
显然
我们考虑进一步优化。(优化成了更加优雅的暴力)
考虑到
设
设
显然的一点是
那么我们开始可以先让
然后如果我们发现
显然 , 这时候前面所有和他编号相同的店铺都可以选到
因此此时让
(想不到线性做法的蒟蒻只能用数据结构硬怼)
//优雅的暴力
#include <bits/stdc++.h>
#define ls(x) x << 1
#define rs(x) x << 1 | 1
using namespace std;
const int maxn = 200000 + 10;
int n , k , p;
int f[maxn] , g[maxn] , num[maxn];
struct Node {
int val , col;
}a[maxn];
struct Segment_Tree {
int l , r , dis;
}t[maxn << 2];
void pushup(int x) {t[x].dis = min(t[ls(x)].dis , t[rs(x)].dis);}
void built(int x , int l ,int r ) {
t[x].l = l , t[x].r = r;
if(l == r) {t[x].dis = a[l].val; return;}
int mid = (l + r) >> 1;
built(ls(x) , l , mid); built(rs(x) , mid + 1 , r);
pushup(x);
}
int query(int x, int l, int r) {
if(t[x].l >= l && t[x].r <= r) {return t[x].dis;}
int mid = (t[x].l + t[x].r) >> 1;
int ans = 0x7fffffff;
if(l <= mid) ans = min(ans , query(ls(x) , l , r));
if(r > mid) ans = min(ans , query(rs(x) , l , r));
return ans;
}
int main () {
scanf("%d%d%d" ,&n , &k ,&p);
for(int i = 1 ; i <= n ; ++ i) {
scanf("%d%d", &a[i].col , &a[i].val);
if(!g[a[i].col]) g[a[i].col] = i;
}
built(1 , 1 , n);
for(int i = 1 ; i <= n ; ++ i) {
f[i] = f[g[a[i].col]];
if(i == g[a[i].col]) {num[a[i].col] ++;continue;}
if(query(1 , g[a[i].col] ,i) <= p) f[i] = num[a[i].col];
g[a[i].col] = i;
num[a[i].col] ++;
}
int ans = 0;
for(int i = 1 ; i <= n ; ++ i) {
ans += f[i];
}
printf("%d\n" , ans);
return 0;
}