Codeforces Round #344 (Div. 2)C. Report

题意:一个数组,两种操作,1把1到r变成递增,2把1到r变成递减

解法:首先可以明确的是有效操作r肯定是递减的(因为不递减后面的操作会覆盖前面的操作),1,2然后肯定是交替的,因为如果不是交替的,那么结果不会变,所以是无效操作,

然后我们想办法解决这个有效操作,可以用splay打翻转标记

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=200000+10,maxn=50+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

int a[N];
struct Splay{
    struct Node{
        Node* ch[2];
        int v;
        int s;
        int flip;
        int cmp(int x)const{
            int d = x - ch[0]->s;
            if(d==1)return -1;
            return d<=0 ? 0:1;
        }
        void maintain()
        {
            s = 1 + ch[0]->s + ch[1]->s;
        }
        void pushdown()
        {
            if(flip)//类似于线段树的lazy标记
            {
                flip=0;
                swap(ch[0],ch[1]);
                ch[0]->flip = !(ch[0]->flip);
                ch[1]->flip = !(ch[1]->flip);
            }
        }
    };
    Node* null;
    void Rotate(Node* &o,int d)
    {
        Node* k = o->ch[d^1];
        o->ch[d^1] = k->ch[d];
        k->ch[d] = o;
        o->maintain();k->maintain();
        o = k;
    }
    void splay(Node* &o,int k)
    {
        o->pushdown();
        int d = o->cmp(k);
        if(d==1)k -= o->ch[0]->s + 1;//利用二叉树性质
        if(d!=-1)
        {
            Node* p = o->ch[d];
            p->pushdown();
            int d2 = p->cmp(k);
            int k2 = (d2==0 ? k:k-p->ch[0]->s-1);
            if(d2!=-1)
            {
                splay(p->ch[d2],k2);
                if(d==d2)Rotate(o,d^1);
                else Rotate(o->ch[d],d);
            }
            Rotate(o,d^1);
        }
    }
    Node* Merge(Node* left,Node* right)
    {
        splay(left,left->s);//把排名最大的数splay到根
        left->ch[1] = right;
        left->maintain();
        return left;
    }
    void split(Node* o,int k,Node* &left,Node* &right)
    {
        splay(o,k);//把排名为k的节点splay到根,右侧子树所有节点排名比k大,左侧小
        right = o->ch[1];
        o->ch[1] = null;
        left = o;
        left->maintain();
    }
    Node *root,*left,*right;
    void init(int sz)
    {
        null=new Node;
        null->s=0;
        root=new Node;
        root->v=a[1];root->flip=0;
        root->ch[0]=root->ch[1]=null;
        root->maintain();
        Node* p;
        for(int i=2;i<=sz;i++)
        {
            p=new Node;
            p->v=a[i];p->s=p->flip=0;
            p->ch[0]=root,p->ch[1]=null;
            root=p;
            root->maintain();
        }
    }
    void print(Node *o)
    {
        o->pushdown();
        if(o->ch[0]!=null)print(o->ch[0]);
        printf("%d ",o->v);
        if(o->ch[1]!=null)print(o->ch[1]);
    }
}sp;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    stack<pair<int,int> >s;
    for(int i=0;i<m;i++)
    {
        int t,r;scanf("%d%d",&t,&r);
        while(!s.empty()&&s.top().se<=r)s.pop();
        if(s.empty())s.push(mp(t,r));
        else if(s.top().fi!=t)s.push(mp(t,r));
    }
//    while(!s.empty())printf("%d %d\n",s.top().fi,s.top().se),s.pop();
    vector<pair<int,int> >v;
    while(!s.empty())v.pb(s.top()),s.pop();
    reverse(v.begin(),v.end());
//    for(int i=0;i<v.size();i++)printf("%d+++%d\n",v[i].fi,v[i].se);
    sort(a+1,a+v[0].se+1);
//    for(int i=1;i<=n;i++)printf("%d\n",a[i]);
    sp.init(n);
    for(int i=0;i<v.size();i++)
    {
        if(i==0&&v[i].fi==1)continue;
        int t=v[i].fi,r=v[i].se;
        if(r==n)sp.root->flip^=1;
        else
        {
            sp.split(sp.root,v[i].se,sp.left,sp.right);
            sp.left->flip^=1;
            sp.root=sp.Merge(sp.left,sp.right);
        }
    }
    sp.print(sp.root);puts("");
    return 0;
}
/********************
5 4
2 1 3 5 4
1 5
2 5
1 5
2 5
********************/
splay

也可以直接维护最后的区间,用栈保存答案

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200000+10,maxn=1000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

int a[N];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    stack<pair<int,int> >s;
    for(int i=0;i<m;i++)
    {
        int t,r;scanf("%d%d",&t,&r);
        while(!s.empty()&&s.top().se<=r)s.pop();
        if(s.empty())s.push(mp(t,r));
        else if(s.top().fi!=t)s.push(mp(t,r));
    }
    vector<pair<int,int> >v;
    while(!s.empty())v.pb(s.top()),s.pop();
    reverse(v.begin(),v.end());
    sort(a+1,a+v[0].se+1);
//    for(int i=1;i<=n;i++)printf("%d ",a[i]);puts("");
//    for(int i=0;i<v.size();i++)printf("%d+++%d\n",v[i].fi,v[i].se);
    stack<int>st;
    int l=1,r=n,now=1;
    for(int i=0;i<v.size();i++)
    {
        int num=r-l+1-v[i].se;
        if(now==1)
        {
            for(int j=r;num!=0;j--,num--)
                st.push(a[j]);
            num=r-l+1-v[i].se;
            r=r-num;
        }
        else
        {
            for(int j=l;num!=0;j++,num--)
                st.push(a[j]);
            num=r-l+1-v[i].se;
            l+=num;
        }
        now=v[i].fi;
    }
    if(v[v.size()-1].fi==2)
    {
        for(int i=l;i<=r;i++)
            st.push(a[i]);
    }
    else
    {
        for(int i=r;i>=l;i--)
            st.push(a[i]);
    }
    while(!st.empty())printf("%d ",st.top()),st.pop();
    return 0;
}
/***********************
10 3
6 4 0 2 -3 7 8 -9 1 5
1 8
1 4
2 2
***********************/
stack

猜你喜欢

转载自www.cnblogs.com/acjiumeng/p/8954596.html