zoukankan      html  css  js  c++  java
  • POJ3580 SuperMemo splay伸展树,区间操作

    题意:实现一种数据结构,支持对一个数列的 6 种操作:
    第 x 个数到第 y 个数之间的数每个加 D;
    第 x 个数到第 y 个数之间全部数翻转;
    第 x 个数到第 y 个数之间的数,向后循环流动 c 次,即后面 c个数变成这段子序列的最前面 c 个,前面的被挤到后面。
    在第 x 个数后面插入一个数 P。
    删除第 x 个数。
    求第 x 个数到第 y 个数之间的最小数字。

    题解:

    (待补)

    代码先放上:

    (是真的长啊,我已经是比较压行的选手了,依然写了230行)

    1.利用stack回收内存池

    #include <cstdio>
    #include <stack>
    #include <cstring>
    #include <vector>
    #define ll long long
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=1e6+10,maxm=2e6+10;
    const int INF=0x3f3f3f3f;
    class splaytree{
    	public:
    	struct splaynode{
    		splaynode *son[2],*pre;
    		ll val,tag,mn;
    		int size,rev;
    		void init(ll x){
    			pre=son[1]=son[0]=NULL;
    			mn=val=x;
    			tag=rev=0;
    			size=1;
    		}
    		void add(ll x){tag+=x,mn+=x;}
    	};
    	typedef struct splaynode* nodep;
      int cnt;
      stack<nodep> stk;
      nodep root;
    	vector<splaynode> node;
      int getsize(nodep x){return x?x->size:0;}
      void pushdown(nodep now){
        if(!now) return ;
        if(now->tag){
          ll tag=now->tag;
          now->val+=tag;
          if(now->son[0]) now->son[0]->add(tag);
          if(now->son[1]) now->son[1]->add(tag);
          now->tag=0;
        }
        if(now->rev){
          swap(now->son[0],now->son[1]);
          now->rev=0;
          if(now->son[0]) now->son[0]->rev^=1;
          if(now->son[1]) now->son[1]->rev^=1;
        }
      }
      void pushup(nodep now){
        if(!now) return ;
        now->size=1,now->mn=now->val;
        if(now->son[0]) {
          now->mn=min(now->mn,now->son[0]->mn);
          now->size+=now->son[0]->size;
        }
        if(now->son[1]){
          now->mn=min(now->mn,now->son[1]->mn);
          now->size+=now->son[1]->size;
        }
      }
      void rotate(nodep now,int d){
        nodep fa=now->pre;
        pushdown(fa);
        pushdown(now);
        pushdown(now->son[d]);
        fa->son[!d]=now->son[d];
        if(now->son[d]) now->son[d]->pre=fa;
        now->pre=fa->pre;
        if(fa->pre){
          if(fa->pre->son[0]==fa) fa->pre->son[0]=now;
          else fa->pre->son[1]=now;
        }else root=now;
        now->son[d]=fa;
        fa->pre=now;
        pushup(fa);
      }
      void splay(nodep now,nodep dst){
        pushdown(now);
        while(now!=dst){
          if(now->pre==dst){
            if(dst->son[0]==now) rotate(now,1);
            else rotate(now,0);
            break;
          }
          nodep fa=now->pre,gfa=fa->pre;
          if(gfa->son[0]==fa){
            if(fa->son[0]==now) {rotate(fa,1);rotate(now,1);}
            else {rotate(now,0);rotate(now,1);}
          }else {
            if(fa->son[1]==now) {rotate(fa,0);rotate(now,0);}
            else {rotate(now,1);rotate(now,0);}
          }
          if(gfa==dst) break;
          pushup(now);
        }
        pushup(now);
      }
      void find(int k,nodep fa){
        int tmp;
        nodep t=root;
        while (1) {
          pushdown(t);
          tmp=getsize(t->son[0]);
          if (k==tmp+1) break;
          if (k<=tmp) t=t->son[0];
          else {
            k-=tmp+1,t=t->son[1];
          }
        }
        pushdown(t);
        splay(t, fa);
      }
      void findseg(int s,int t){
        find(s,root);
        find(t+2,root->son[1]);
      }
      void insert(int pos,ll val){
        findseg(pos+1,pos);
        nodep now,fa=root->son[1];
        pushdown(root);
        pushdown(fa);
        if(!stk.empty()){
          now=stk.top();
          stk.pop();
        }else now=&node[cnt++];
        now->init(val);
        now->son[1]=fa;
        fa->pre=now;
        root->son[1]=now;
        now->pre=root;
        splay(fa,root);
      }
      void add(int s,int t,ll val){
        findseg(s,t);
        nodep now = root->son[1]->son[0];
        pushdown(now);
        pushup(now);
        now->mn+=val;
        now->tag+=val;
        splay(now,root);
      }
      void reverse(int s,int t){
        findseg(s,t);
        root->son[1]->son[0]->rev^=1;
        nodep now=root->son[1]->son[0];
        splay(now,root);
      }
      void revolve(int s,int t,int len){
        nodep x,y;
        findseg(s,t);
        find(t+1-len,root->son[1]->son[0]);
        x=root->son[1]->son[0];
        pushdown(x);
        y=x->son[1];
        x->son[1]=NULL;
        find(s+1,root->son[1]->son[0]);
        x=root->son[1]->son[0];
        pushdown(x);
        x->son[0]=y;
        y->pre=x;
        splay(y,root);
      }
      ll getmin(int s,int t) {
        findseg(s,t);
        nodep now=root->son[1];
        pushdown(now);
        now=now->son[0];
        pushdown(now);
        pushup(now);
        return now->mn;
      }
      void erase(int pos){
        findseg(pos, pos);
        pushdown(root->son[1]);
        stk.push(root->son[1]->son[0]);
        root->son[1]->son[0] = NULL;
        nodep now = root->son[1];
        splay(now,root);
      }
      splaytree(ll*a,int n){
    		cnt=0;
    		node.resize(maxn);
        root=&node[cnt++];
        root->init(INF);
        root->son[1]=&node[cnt++];
        root->son[1]->init(INF);
        while (!stk.empty()) stk.pop();
        rep(i,0,n-1) insert(i, a[i]);
      }
    };
    
    
    ll v[maxn];
    int main() {
      int n, m;
      scanf("%d", &n);
      rep(i,0,n-1) scanf("%lld",&v[i]);
      scanf("%d", &m);
      splaytree tree(v, n);
      while (m--) {
        char s[50];
        scanf("%s",s);
        if (s[0]=='A') {
          int l, r, d;
          scanf("%d%d%d",&l,&r,&d);
          tree.add(l,r,d);
        }
        if (s[0]=='R') {
          int l, r;
          scanf("%d%d",&l,&r);
          if (s[3]=='E') tree.reverse(l,r);
          else {
            int k;
            scanf("%d",&k);
            int tn=r-l+1;
            k=(k%tn+tn)%tn;
            if (l==r||k==0) continue;
            tree.revolve(l,r,k);
          }
        }
        if (s[0]=='I') {
          int x, d;
          scanf("%d%d",&x,&d);
          tree.insert(x,d);
        }
        if (s[0]=='D') {
          int x;
          scanf("%d",&x);
          tree.erase(x);
        }
        if (s[0]=='M') {
          int l, r;
          scanf("%d%d",&l,&r);
          printf("%lld
    ",tree.getmin(l,r));
        }
      }
      return 0;
    }
    

    2.不用stack

    #include <iostream>
    #include <vector>
    #define ll long long
    #define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
    using namespace std;
    const int maxn=1e6+10,maxm=2e6+10;
    const int INF=0x3f3f3f3f;
    class splaytree{
    	public:
    	struct splaynode{
    		splaynode *son[2],*pre;
    		ll val,tag,mn;
    		int size,rev;
    		void init(ll x){
    			pre=son[1]=son[0]=NULL;
    			mn=val=x;
    			tag=rev=0;
    			size=1;
    		}
    		void add(ll x){tag+=x,mn+=x;}
    	};
    	typedef struct splaynode* nodep;
      int cnt;
      nodep root;
    	vector<splaynode> node;
      int getsize(nodep x){return x?x->size:0;}
      void pushdown(nodep now){
        if(!now) return ;
        if(now->tag){
          ll tag=now->tag;
          now->val+=tag;
          if(now->son[0]) now->son[0]->add(tag);
          if(now->son[1]) now->son[1]->add(tag);
          now->tag=0;
        }
        if(now->rev){
          swap(now->son[0],now->son[1]);
          now->rev=0;
          if(now->son[0]) now->son[0]->rev^=1;
          if(now->son[1]) now->son[1]->rev^=1;
        }
      }
      void pushup(nodep now){
        if(!now) return ;
        now->size=1,now->mn=now->val;
        if(now->son[0]) {
          now->mn=min(now->mn,now->son[0]->mn);
          now->size+=now->son[0]->size;
        }
        if(now->son[1]){
          now->mn=min(now->mn,now->son[1]->mn);
          now->size+=now->son[1]->size;
        }
      }
      void rotate(nodep now,int d){
        nodep fa=now->pre;
        pushdown(fa);
        pushdown(now);
        pushdown(now->son[d]);
        fa->son[!d]=now->son[d];
        if(now->son[d]) now->son[d]->pre=fa;
        now->pre=fa->pre;
        if(fa->pre){
          if(fa->pre->son[0]==fa) fa->pre->son[0]=now;
          else fa->pre->son[1]=now;
        }else root=now;
        now->son[d]=fa;
        fa->pre=now;
        pushup(fa);
      }
      void splay(nodep now,nodep dst){
        pushdown(now);
        while(now!=dst){
          if(now->pre==dst){
            if(dst->son[0]==now) rotate(now,1);
            else rotate(now,0);
            break;
          }
          nodep fa=now->pre,gfa=fa->pre;
          if(gfa->son[0]==fa){
            if(fa->son[0]==now) {rotate(fa,1);rotate(now,1);}
            else {rotate(now,0);rotate(now,1);}
          }else {
            if(fa->son[1]==now) {rotate(fa,0);rotate(now,0);}
            else {rotate(now,1);rotate(now,0);}
          }
          if(gfa==dst) break;
          pushup(now);
        }
        pushup(now);
      }
      void find(int k,nodep fa){
        int tmp;
        nodep t=root;
        while (1) {
          pushdown(t);
          tmp=getsize(t->son[0]);
          if (k==tmp+1) break;
          if (k<=tmp) t=t->son[0];
          else {
            k-=tmp+1,t=t->son[1];
          }
        }
        pushdown(t);
        splay(t, fa);
      }
      void findseg(int s,int t){
        find(s,root);
        find(t+2,root->son[1]);
      }
      void insert(int pos,ll val){
        findseg(pos+1,pos);
        nodep now,fa=root->son[1];
        pushdown(root);
        pushdown(fa);
        now=&node[cnt++];
        now->init(val);
        now->son[1]=fa;
        fa->pre=now;
        root->son[1]=now;
        now->pre=root;
        splay(fa,root);
      }
      void add(int s,int t,ll val){
        findseg(s,t);
        nodep now = root->son[1]->son[0];
        pushdown(now);
        pushup(now);
        now->mn+=val;
        now->tag+=val;
        splay(now,root);
      }
      void reverse(int s,int t){
        findseg(s,t);
        root->son[1]->son[0]->rev^=1;
        nodep now=root->son[1]->son[0];
        splay(now,root);
      }
      void revolve(int s,int t,int len){
        nodep x,y;
        findseg(s,t);
        find(t+1-len,root->son[1]->son[0]);
        x=root->son[1]->son[0];
        pushdown(x);
        y=x->son[1];
        x->son[1]=NULL;
        find(s+1,root->son[1]->son[0]);
        x=root->son[1]->son[0];
        pushdown(x);
        x->son[0]=y;
        y->pre=x;
        splay(y,root);
      }
      ll getmin(int s,int t) {
        findseg(s,t);
        nodep now=root->son[1];
        pushdown(now);
        now=now->son[0];
        pushdown(now);
        pushup(now);
        return now->mn;
      }
      void erase(int pos){
        findseg(pos, pos);
        pushdown(root->son[1]);
        root->son[1]->son[0] = NULL;
        nodep now = root->son[1];
        splay(now,root);
      }
      splaytree(vector<int> num,int n){
      	cnt=0;
    		node.resize(n+7);
        root=&node[cnt++];
        root->init(INF);
        root->son[1]=&node[cnt++];
        root->son[1]->init(INF);
        int size=num.size();
    		rep(i,0,size-1) insert(i, num[i]);
      }
    };
    int main() {
    	ios::sync_with_stdio(false),cin.tie(0);
      int n,m;
      cin>>n;
      vector<int> v(n);
      rep(i,0,n-1) cin>>v[i];
      cin>>m;
      splaytree tree(v,n+m);
      while (m--) {
        string s;
        cin>>s;
        if (s[0]=='A') {
          int l,r,d;cin>>l>>r>>d;
          tree.add(l,r,d);
        }
        if (s[0]=='R') {
          int l,r;cin>>l>>r;
          if (s[3]=='E') tree.reverse(l,r);
          else {
            int k;cin>>k;
            int tn=r-l+1;
            k=(k%tn+tn)%tn;
            if (l==r||k==0) continue;
            tree.revolve(l,r,k);
          }
        }
        if (s[0]=='I') {
          int x,d;cin>>x>>d;
          tree.insert(x,d);
        }
        if (s[0]=='D') {
          int x;cin>>x;
          tree.erase(x);
        }
        if (s[0]=='M') {
          int l,r;cin>>l>>r;
          cout<<tree.getmin(l,r)<<endl;
        }
      }
      return 0;
    }
    

      

  • 相关阅读:
    制作IOS 后台极光推送时,遇到的小问题
    如何实现IOS_SearchBar搜索栏及关键字高亮
    使用WKWebView替换UIWebView,并且配置网页打电话功能
    [Creating an image format with an unknown type is an error] on cordova, ios 10
    面向对象语言还需要指针么?
    推荐一个简单好用的接口——字典序列化
    ITTC数据挖掘系统(六)批量任务,数据查看器和自由文档
    java的LINQ :Linq4j简明介绍
    别语言之争了,最牛逼的语言不是.NET,也不是JAVA!
    ITTC数据挖掘平台介绍(五) 数据导入导出向导和报告生成
  • 原文地址:https://www.cnblogs.com/nervendnig/p/10217780.html
Copyright © 2011-2022 走看看