Codeforces Round #452 D 思维 E 链表+堆 F 树状数组+set

Codeforces Round #452 (Div. 2)

D. Shovel Sale

题意:给出数 n ,你可以在 1~n 里面选取两个数,使得两数之和要尽可能以更多的 9 结尾。 问方案数。

tags:先算出结尾要多少个 9 ,然后在开头加一个数字。比如  n=50 ,最多是 99,在开头加一个数字,即  p = i 99 。

可以相加得到 p 的方案有:

1     p-1

2     p-2

3     p-3

.......

(p-1)/2    (p+1)/2

最后相加即可。

n<5 的时候,是 0 个9 。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

ll  n;
int main()
{
    scanf("%lld", &n);
    if(n<5) return 0*printf("%lld", n*(n-1)/2);
    int cnt=0;
    ll  sum=1, ans=0, sum1=0;
    for(ll num=5; num<=n; ++cnt, num*=10, sum1+=sum*9, sum*=10) ;
    rep(i,0,8)
    {
        ll  p = 1LL*i*sum + sum1;
        if(p<=n)
            ans += (p-1)/2;
        else if((p+1)/2<=n && n<p)
            ans += n-(p+1)/2+1;
    }
    printf("%lld
", ans);

    return 0;
}
View Code

E. Segments Removal

题意:给出一个序列,每次从序列中删除最长最左边的连续相同子序列。问要多少次删完。

tags:链表把相同的连起来,再用堆每次选出最长最左边的。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

int n, a[N], cnt;
bool vis[N<<2];
struct Node
{
    int id, pre, next, fir, ai, len;
    bool friend operator < (Node a, Node b) {
        if(a.len==b.len) return a.fir > b.fir;
        return a.len < b.len;
    }
} p[N<<2];
priority_queue< Node > q;
int main()
{
    scanf("%d", &n);
    rep(i,1,n)
    {
        scanf("%d", &a[i]);
        if(a[i-1]==a[i]) {
            ++p[cnt].len;
        }
        else {
            ++cnt;
            p[cnt] = (Node){ cnt, cnt-1, cnt+1, i, a[i], 1 };
        }
        if(i==n) p[cnt].next=0;
    }
    rep(i,1,cnt) q.push(p[i]);
    int ans=0;
    Node u;
    while(!q.empty())
    {
        u = q.top();  q.pop();
        if(vis[u.id]) continue;
        u = p[u.id];
        ++ans;
        vis[u.id] = true;
        if(u.pre==0 || u.next==0)
        {
            p[u.pre].next = u.next;
            p[u.next].pre = u.pre;
        }
        else
        {
            if(p[u.pre].ai==p[u.next].ai)
            {
                ++cnt;
                p[cnt] = (Node){ cnt, p[u.pre].pre, p[u.next].next, p[u.pre].fir, p[u.pre].ai, p[u.pre].len+p[u.next].len };
                p[p[u.pre].pre].next = cnt;
                p[p[u.next].next].pre = cnt;
                vis[u.pre] = vis[u.next] = true;
                q.push(p[cnt]);
            }
            else
            {
                p[u.pre].next = u.next;
                p[u.next].pre = u.pre;
            }
        }
    }
    printf("%d
", ans);

    return 0;
}
View Code

F. Letters Removing

题意:长度为 n 的字符串,只包含 大、小写字母和0~9数字。 有 m 个操作 l, r, c:每次删除区间 [l,r] 内的 c 字符, (给出的 l、r 是相对删除之后重新确定的位置,不是初始位置)。 求最后剩下的字符串。

tags: 好题,set 部分可以用平衡树,还不会平衡树,待补

1】每次给出的 l, r,我们把它还原回初始的位置。这个用树状数组即可,还存在的记为1,删去了的为0。

2】开62个set,在每个 set 里存对应的字符的所有位置。 每次操作在对应的set里删除在 l,r 之间的即可。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

int n, m, bit[N];
char str[N];
set<int > Set[65];
void Add(int x, int y) {
    for(int i=x; i<N; i+=i&-i)
        bit[i] += y;
}
int query(int x) {
    int ans=0;
    for(int i=x; i; i-=i&-i)
        ans += bit[i];
    return ans;
}
int get(char ch) {
    if('a'<=ch && ch<='z') return ch-'a'+1;
    else if('A'<=ch && ch<='Z') return ch-'A'+27;
    else return ch-'0'+53;
}
int get2(int x) {
    int l=1, r=n, mid, ans;
    while(l<=r) {
        mid = l+r>>1;
        if(query(mid)>=x) r=mid-1, ans=mid;
        else l=mid+1;
    }
    return ans;
}
int main()
{
    scanf("%d%d", &n, &m);
    scanf("%s", str+1);
    int tmp;
    rep(i,1,n) {
        Add(i, 1);
        tmp = get(str[i]);
        Set[tmp].insert(i);
    }
    int l, r, tl, tr;
    char ch;
    set<int >::iterator  it, posl, it2;
    rep(i,1,m)
    {
        scanf("%d%d%*c%c", &l, &r, &ch);
        tl = get2(l);
        tr = get2(r);
        tmp = get(ch);
        posl = Set[tmp].lower_bound(tl);
        it = posl;
        while(it!=Set[tmp].end() && *it<=tr)
        {
            Add((*it), -1);
            it2 = it;
            ++it;
            Set[tmp].erase(it2);
        }
    }
    rep(i,1,n)
        if(query(i)!=query(i-1))
            putchar(str[i]);

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/sbfhy/p/8318477.html