Codeforces 387E George and Cards 树状数组 + 集合set查询

来源:互联网 发布:aspnet源码 编辑:程序博客网 时间:2024/06/06 07:45

题目大意:

就是现在有n章卡片的排列p1, p2...pn, 每张卡片上写着1~n, 现在George进行n - k次remove的操作, 使得最后只剩下的牌为b1, b2...bk, 每次remove操作可以选择一段连续的区间x1, x2...xw, 然后从中移除最小的那个, 注意移除最小的那个之后剩下的卡片保持连在一起, 完成这样一次操作会得到w份香肠, 为了使最后剩下的牌的排列为b1, b2, b3 ... bk, 应该怎样选使得得到的香肠最多, 输出最多能得到的香肠份数


大致思路:

先找到贪心的思路然后就是用树状数组维护一下了...注意set当中upper_bound函数和lower_bound函数的区别


代码如下:

Result  :  Accepted     Memory  :  71500 KB     Time  :  1497 ms

/* * Author: Gatevin * Created Time:  2015/3/10 15:12:18 * File Name: Kotori_Itsuka.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;/* * 首先不难想到贪心的思想, 每次选择移除能够移除的最小的那个数 * 这样多次选择之后区间长度综合才最大 */int n, k;int pos[1000010];//数值为i的数的位置pos[i]bool keep[1000010];//最后i是否需要留下来为keep[i]int C[1000010];set<int> S, T;//集合S中是需要保留的位置, 并且变化, 随着贪心接下来要选择移除的数而变化//树状数组维护方便查询某区间当中已经被移除的数int lowbit(int x){    return -x & x;}void add(int x, int value){    while(x <= n)        C[x] += value, x += lowbit(x);    return;}int ask(int L, int R){    int ret = 0;    while(R)        ret += C[R], R -= lowbit(R);    while(L)        ret -= C[L], L -= lowbit(L);    return ret;}int main(){    scanf("%d %d", &n, &k);    int tmp;    for(int i = 1; i <= n; i++)        scanf("%d", &tmp), pos[tmp] = i;    for(int i = 1; i <= k; i++)        scanf("%d", &tmp), keep[tmp] = 1;    S.insert(0); S.insert(n + 1);    T.insert(0); T.insert(-n - 1);    lint ans = 0;    for(int i = 1; i <= n; i++)//贪心思想枚举接下来要选择删除的数        if(keep[i])            S.insert(pos[i]), T.insert(-pos[i]);        else        {            int R = *S.upper_bound(pos[i]);            //int L = *S.lower_bound(pos[i] - 1);            //low_bound(x)返回的是不比x小的第一个数的地址, 不是小于x的最大的            int L = -*T.upper_bound(-pos[i]);            ans += (R - L - 1);            ans -= ask(L, R - 1);//这段区间(L, R)当中已经被删除的元素            add(pos[i], 1);        }    printf("%I64d\n", ans);    return 0;}


0 0
原创粉丝点击