「6月雅礼集训 2017 Day7」回转寿司

【题目大意】

给一个n个数的序列,q次操作,每次选择区间$[l,r]$,给出数p,对于区间$[l,r]$的每个数$x$,做如下操作:

如果$x > p$,就交换$x$和$p$。求每次操作后$p$的值。

$1leq nleq 4 imes 10^5, 1leq q leq 25000$

【题解】

这个q的范围就提示我们可以用根号算法了(逃)

由于有一个性质,p最后一定是变成[l,r]区间内最大的那个数,可是还要修改,所以我们需要分块。

我们对于区间分块,然后对于每个块维护一个堆存储元素,同时维护一个tag维护这个块被几个p给做过操作(由于做操作的时候,如果是一整块,那么我们知道这块做完后,答案一定是这块的最大值和p中取个最大的,所以我们不需要实际做操作,只要打个tag即可)

当访问到块内(头、尾),我们把块内的tag传到值上,我们一定是用tag这个堆里最小的跟区间的每个值依次比较,比较成功就交换,我们可以用堆。

还有一些优化就是我们用vector存tag,然后用强制类型转换来线性建堆(?)

我们修改直接应用在数组上,修改完,再把数组拿去线性建堆(?)

然后你96分了。。换一个读入优化板子就过了。

# include <queue>
# include <math.h>
# include <ctype.h>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

const int N = 4e5 + 10, M = 2e5 + 10, F = 3010;

# define RG register
# define ST static

int n, Q, BLOCK, B;
ST int a[N], bl[N];
ST int bg[F], ed[F];

#define BUFSIZE 300000
namespace fib {char b[BUFSIZE]={},*f=b;}
#define gc ((*fib::f)?(*(fib::f++)):(fgets(fib::b,sizeof(fib::b),stdin)?(fib::f=fib::b,*(fib::f++)):-1))
int g_i()
{
    int tmp=0; bool fu=0; char s;
    while(s=gc,s!='-'&&(s<'0'||s>'9')) ;
    if(s=='-') fu=1; else tmp=s-'0';
    while(s=gc,s>='0'&&s<='9') tmp=tmp*10+s-'0';
    if(fu) return -tmp; else return tmp;
}
#define gi g_i()
namespace fob {char b[BUFSIZE]={},*f=b,*g=b+BUFSIZE-2;}
#define pob (fwrite(fob::b,sizeof(char),fob::f-fob::b,stdout),fob::f=fob::b,0)
#define pc(x) (*(fob::f++)=(x),(fob::f==fob::g)?pob:0)
struct foce {~foce() {pob; fflush(stdout);}} _foce;
namespace ib {char b[100];}
inline void pint(int x)
{
    if(x==0) {pc(48); return;}
    if(x<0) {pc('-'); x=-x;}
    char *s=ib::b;
    while(x) *(++s)=x%10, x/=10;
    while(s!=ib::b) pc((*(s--))+48);
}



priority_queue<int> q[F];
vector<int> tag[F];

inline void rebuild(int id) {
    RG int l = bg[id], r = ed[id];
    q[id] = priority_queue<int> (a+l, a+r+1);
}

inline void tagdown(int id) {
    if(!tag[id].size()) return ;
    priority_queue < int, vector<int>, greater<int> > heap(tag[id].begin(), tag[id].end());
    for (RG int i=bg[id], tp; i<=ed[id]; ++i) {
        tp = heap.top();
        if(a[i] > tp) {
            heap.pop();
            heap.push(a[i]);
            a[i] = tp;
        }
    }
    rebuild(id);
    tag[id].clear();
}

// tag down and force
inline int work(int id, int l, int r, int p) {
    tagdown(id);
    for (int i=l; i<=r; ++i) if(a[i] > p) swap(a[i], p);
    rebuild(id);
    return p;
}

// cover whole
inline int work(int id, int p) {
    RG int tp = q[id].top();
    if(tp > p) {
        tag[id].push_back(p);
        q[id].pop();
        q[id].push(p);
        p = tp;
    }
    return p;
} 

inline int solve(int l, int r, int p) {
    int BL = bl[l], BR = bl[r]; 
    if(BL == BR) return work(BL, l, r, p);
    else {
        p = work(BL, l, ed[BL], p);
        for (int i=BL+1; i<BR; ++i) p = work(i, p);
        return work(BR, bg[BR], r, p);
    }    
}

int main() {
//    freopen("sushi.in", "r", stdin);
//    freopen("sushi.out", "w", stdout);
    n = gi; Q = gi;
    for (RG int i=1; i<=n; ++i) a[i] = gi;
    BLOCK = sqrt(n); 
    for (RG int i=1; i<=n; ++i) bl[i] = (i-1) / BLOCK + 1;
    B = bl[n];
    for (RG int i=1; i<=B; ++i) {
        bg[i] = (i-1) * BLOCK + 1;
        ed[i] = i * BLOCK;
        if(i == B) ed[i] = n;
    }
    for (RG int i=1; i<=n; ++i) q[bl[i]].push(a[i]);
    RG int l, r, p;
    while(Q --) {
        l = gi, r = gi, p = gi;
        if(l <= r) pint(solve(l, r, p)), pc(10);
        else {
            p = solve(l, n, p);
            pint(solve(1, r, p)), pc(10);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/galaxies/p/20170623_c.html