Codefoeces 387E - George and Cards 贪心+线段树

首先要知道每次拿走最小才会达到最优,因为最小的不会给其他的提供任何加分,只有可能减小加分。

删除卡片的次序确定了,剩下的就是确定每段区间的左右端点。

pos[i] 表示数字 i 在初始序列中的位置。

首先枚举i (i = 1 -> n),如果不需删除,则将pos[i]放入set<int> S中,如果不需删除,则在S中二分查找上下界。

总的时间复杂度为o(  (n-k)*log(k)  )。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <iomanip>

#pragma comment(linker,"/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define Mod 1000000007
#define mod 1000000007

/** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
    char c;
    while(!d);
    x=c-'0';
    while(d)p;
    return x;
}
template<class T> inline T& RDD(T &x)
{
    char c;
    while(g,c!='-'&&!isdigit(c));
    if (c=='-')
    {
        x='0'-g;
        while(d)n;
    }
    else
    {
        x=c-'0';
        while(d)p;
    }
    return x;
}
inline double& RF(double &x)      //scanf("%lf", &x);
{
    char c;
    while(g,c!='-'&&c!='.'&&!isdigit(c));
    if(c=='-')if(g=='.')
        {
            x=0;
            double l=1;
            while(d)nn;
            x*=l;
        }
        else
        {
            x='0'-c;
            while(d)n;
            if(c=='.')
            {
                double l=1;
                while(d)nn;
                x*=l;
            }
        }
    else if(c=='.')
    {
        x=0;
        double l=1;
        while(d)pp;
        x*=l;
    }
    else
    {
        x=c-'0';
        while(d)p;
        if(c=='.')
        {
            double l=1;
            while(d)pp;
            x*=l;
        }
    }
    return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g
using namespace std;

int num[1000010];
int pos[1000010];
bool ap[1000010];

int st[4001000];

set<int> s;

int Init(int site,int l,int r)
{
    if(l == r)
        return st[site] = 1;

    int mid = (l+r)>>1;

    return st[site] = Init(site<<1,l,mid) + Init(site<<1|1,mid+1,r);
}

int Query(int site,int L,int R,int l,int r)
{
    if(L == l && R == r)
        return st[site];

    int mid = (L+R)>>1;

    if(r <= mid)
        return Query(site<<1,L,mid,l,r);
    if(mid < l)
        return Query(site<<1|1,mid+1,R,l,r);
    return Query(site<<1,L,mid,l,mid) + Query(site<<1|1,mid+1,R,mid+1,r);
}

void Update(int site,int l,int r,int x)
{
    if(l == r)
    {
        st[site] = 0;
        return ;
    }

    int mid = (l+r)>>1;

    if(x <= mid)
        Update(site<<1,l,mid,x);
    else
        Update(site<<1|1,mid+1,r,x);

    st[site] = st[site<<1] + st[site<<1|1];
}

int main()
{
    int n,k,i,j,x;

    scanf("%d %d",&n,&k);

    for(i = 1;i <= n; ++i)
        scanf("%d",&num[i]),pos[num[i]] = i;

    memset(ap,false,sizeof(ap));

    for(i = 1;i <= k; ++i)
        scanf("%d",&x),ap[x] = true;

    set<int>::iterator it;

    LL sum = 0;

    Init(1,1,n);
    s.insert(n+1);
    s.insert(0);
    for(i = 1;i <= n; ++i)
    {
        if(ap[i])
        {
            s.insert(pos[i]);
            continue;
        }

        it = s.upper_bound(pos[i]);

        int r = *it-1;
        int l = *(--it)+1;

        sum += Query(1,1,n,l,r);
        Update(1,1,n,pos[i]);
    }

    cout<<sum<<endl;

    return 0;
}
时间: 2024-11-10 04:08:45

Codefoeces 387E - George and Cards 贪心+线段树的相关文章

【tyvj】P2065 「Poetize10」封印一击(贪心+线段树/差分)

http://new.tyvj.cn/p/2065 我就不说我很sb的用线段树来维护值...... 本机自测的时候想了老半天没想出怎么维护点在所有区间被多少区间包含的方法.最后一小时才想出来线段树(果然太弱) .. 首先想到贪心,答案一定是某个区间的右端点...(这个很容易想也容易证,我就不说了.....) 然后按右端点排序 然后我维护了个左端点前缀和,将来枚举每一个右端点的时候所得到的答案就是sum[n]-sum[i]-he+ge*a[i].r he表示包含右端点的所有区间的左端点之和,ge表

Codeforces Round #401 (Div. 2) E 贪心,线段树

Codeforces Round #401 (Div. 2) A 循环节 B 暴力排一下 C 标记出来,但10^5,特耿直地码了个O(n^2)的上去,最气的是在最后3分钟的时候被叉== D 从后往前贪心暴糙一下就好.比赛时一眼瞄出来了不敢写,搞不懂这样竟然不会超时.. E. Hanoi Factory 题意:n个环体,内径a[i],外径b[i],高h[i].当 a[i+1]<b[i]<=b[i+1] 时,第 i 个环体可以堆在第 i+1个环体上.求可以堆出的最高高度. tags:佩服那些大佬,

ACM学习历程——NOJ1113 Game I(贪心 || 线段树)

Description 尼克发明了这样一个游戏:在一个坐标轴上,有一些圆,这些圆的圆心都在x轴上,现在给定一个x轴上的点,保证该点没有在这些圆内(以及圆上),尼克可以以这个点为圆心做任意大小的圆,他想知道自己做多可以与多少个给定的圆相交(相切也算,包含不算). Input 输入有多组数据 输入到文件尾 每一组数据有一个整数n(1<=n<=100000),表示总共有n个圆. 接下是n行,每行两个整数xi,ri表示该圆的圆心坐标和半径. 接下来一行为一个整数x,表示尼克选取点的位置. x xi的范

Codeforces Round #424 (Div. 2) E. Cards Sorting(线段树)

题目链接:Codeforces Round #424 (Div. 2) E. Cards Sorting 题意: 将n个数放进一个队列,每次检查队首,看看是不是队列中最小的数,如果是就扔掉,如果不是就放到队尾. 这样直到队列为空,为需要操作多少次. 题解: 考虑用两个指针模拟,最开始now指针指向第一个数,然后nxt指针指向下一个将要被删除的数. 然后我们要算出这里需要移动多少步,然后删掉这个数,一直重复操作,直到将全部的数删完. nxt指针可以用set来维护,now指针可以用并查集来维护. 计

bzoj 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle【贪心+线段树】

按结束时间排序,然后开个线段树,按照排序后的牛群贪心的选 贪心的依据是选哪头牛都是选,不如给后面的多省一点空间 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=50005; int m,n,c,ans; struct xds { int l,r,mn,lz; }t[N<<1]; struct qwe { int s,t,m; }a

[luoguP3606] [USACO17JAN]Building a Tall Barn建谷仓(贪心 + 线段树)

传送门 把线段都读进来然后排序,先按右端点为第一关键字从小到大排序,后按左端点为第二关键字从小到大排序. 注意不能先按左端点后按右端点排序,否则会出现大包小的情况,如下: —————— ———  — 然后直接线段树搞就行,先求区间最小值,如果大于零就更新统一减1. ——代码 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #define root 1, 1, n 5 #define l

HDU 6047 Maximum Sequence(贪心+线段树)

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6047 题目: Maximum Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 90    Accepted Submission(s): 44 Problem Description Steph is extremely o

Codeforces 387E George and Cards

George and Cards 我们找到每个要被删的数字左边和右边第一个比它小的没被删的数字的位置.然后从小到大枚举要被删的数, 求答案. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pa

Codeforces Round #227 (Div. 2)---E. George and Cards(贪心, 树状数组+set维护, 好题!)

George is a cat, so he loves playing very much. Vitaly put n cards in a row in front of George. Each card has one integer written on it. All cards had distinct numbers written on them. Let's number the cards from the left to the right with integers f