BZOJ-3337ORZJRY I 块状链表

Posted DaD3zZ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ-3337ORZJRY I 块状链表相关的知识,希望对你有一定的参考价值。

3337: ORZJRY I

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 190  Solved: 50
[Submit][Status][Discuss]

Description

Jry最近做(屠)了很多数据结构题,所以想 BS你,他希望你能实现一种数据结构维护一个序列:

技术分享

Input

第一行n;
第二行n个数;
第三行q,代表询问个数;
接下来q行,每行一个op,输入格式见描述。

Output

对于7≤op≤11的操作,一行输出一个答案。

Sample Input

6
5 2 6 3 1 4
15
7 2 4
8 1 3
9 2 4 5
10 1 6 4
11 2 5 4
6 1 4 7
8 1 4
5 3 4 5
2 1
1 2 8
3 3 5
4 1 5 2
9 2 5 4
10 3 6 4
11 1 6 100

Sample Output

11
4
1
4
3
0
3
12
6

HINT

n,q≤100000;
任意时刻数列中的数≤2^31-1。
0≤任意时刻数列中的数≤2^31-1。

本题共3组数据

Source

by orzjry

Solution

switch(opt)
{
  case 1: 直接分裂后插入即可 break;
  case 2: 分裂后直接删除 break;
  case 3: 分裂得到[l,r]将指向l的块指向r,l指向r指向的块,然后给[l,r]中所有块打上反转标记 break;
  case 4: 提取出[r-k,r],将这段从中删除,再整段插入到l之前 break;
  case 5: 提取[l,r],打tag标记 break;
  case 6: 提取[l,r],打del标记 break;
  case 7: 提取[l,r],扫描一遍区间中的所有块,统计sum break;
  case 8: 同上,统计max和min,输出max-min break;
  case 9: 想的还是需要二分,但还没有特别精妙的想法 break;
  case 10: 对每个块额外记录一个排序后的数列,然后找K小 break;
  case 11: 对每个块额外处理一个有序的数列,然后二分统计个数 break;
}

上述这些二分大都可以用STL中的替代,注意的是Split和Merge的时候要PushDown和Update

Code

技术分享
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<0 || ch>9) {if (ch==-) f=-1; ch=getchar();}
    while (ch>=0 && ch<=9) {x=x*10+ch-0; ch=getchar();}
    return x*f;
}

namespace BlockLists
{
    #define BN 
    struct BLNode{int next,from,data[],tmp[],size; int maxx,minn,tag,sum; bool rev;}B[BN];
    queue<int>trash;
    inline int New() {if (trash.empty()) return ++sz; int tmp=trash.front(); trash.pop(); return tmp;}
    inline void Del(int x) {trash.push(x); B[x].next=-1; B[x].size=B[x].maxx=B[x].minn=B[x].sum=B[x].tag=B[x].rev=0;}
    inline int GetP(int rk) {for (int i=start; ~i; i=B[i].next) if (rk>B[i].size) rk-=B[i].size; else return i;}
    inline int GetK(int rk) {for (int i=start; ~i; i=B[i].next) if (rk>B[i].size) rk-=B[i].size; else return rk;}
    inline void Data(int pos,int len,int data[],int suf) {B[pos].next=suf; B[pos].size=len; memcpy(B[pos].data,data,len);}
    inline void PushDown(int x)
    {
        int sz=B[x].size;
        if (B[x].del) {int del=B[x].del; B[x].del=0; for (int i=0; i<sz; i++) B[x].data[i]=del; B[x].sum=sz*del; B[x].maxx=B[x].minn=del;}
        if (B[x].rev) {reverse(B[x].data,B[x].data+sz);}
        if (B[x].tag) {int tag=B[x].tag; B[x].tag=0; for (int i=0; i<sz; i++) B[x].data[i]+=tag; B[x].sum+=sz*tag; B[x].maxx+=tag; B[x].minn+=tag;}
    }
    inline void Update(int x)
    {
        int sz=B[x].size; B[x].sum=0;
        for (int i=0; i<sz; i++) B[x].sum+=B[x].data[i];
        memcpy(B[x].tmp,B[x].data,sz);
        sort(B[x].tmp,B[x].tmp+sz);
    }
    inline void Split(int pos,int rk)
    {
        PushDown(pos);
        if (B[pos]==rk) return;
        int id=New(); Data(id,B[pos].size-rk,B[pos].data+rk,B[pos].next); B[pos].next=id; B[pos].size=rk;
        Update(id); Update(pos);
    }
    inline void Merge(int pos)
    {
        for ( ; ~pos; pos=B[pos].next)
            for (int suf=B[pos].next; ~suf && B[pos].size+B[suf].size<Bsize; suf=B[suf].next)
                PushDown(pos),PushDown(suf),
                memcpy(B[pos].data+B[pos].size,B[suf].data,B[suf].size),B[pos].next=B[suf].next,B[pos].size+=B[suf].size,
                Del(suf),Update(pos);
    }
    inline void Insert(int s)
    {
        int now=GetP(s),pos=GetK(s);  Split(now,pos);
        int id=New(); Data(id,1,a+1,B[now].next); B[now].next=id;
        Merge(now);
    }
    inline void Delete(int s)
    {
        int now=GetP(s),pos=GetK(s); Split(now,pos);
        Del(B[pos].next);
        Merge(now);
    }
    inline void Prework(int l,int r,int &x,int &y)
    {
        int now1=GetP(l),pos1=GetK(l);  Split(now1,pos1);
        int now2=GetP(r),pos2=GetK(r);  Split(now2,pos2);
        x=pos1,y=pos2;
    }
    inline void Rever()
    {
        
    }
    inline void Change()
    inline void Move()
    inline void Add()
    inline void Modify()
    inline void GetSum()
    inline void GetRange()
    inline void GetClose()
    inline void GetKth()
    inline void GetSmall()
}
using namespace BlockLists;
int main()
{
    int N=read();
    for (int i=1; i<=N; i++) a[0]=read(),Insert(i-1);
    Bsize=ceil(sqrt(N));
    Q=read();
    while (Q--)
        {
            int opt=read(); int x,y,k,val;
            switch (opt)
                {
                    case 1: x=read()-1,val=read(),Change(x,val); break;
                    case 2: x=read()-1; Delete(x); break;
                    case 3: x=read()-1,y=read()-1; Rever(x,y); break;
                    case 4: x=read()-1,y=read()-1,k=read(); Move(x,y); break;
                    case 5: x=read()-1,y=read()-1; val=read(); Add(x,y,val); break;
                    case 6: x=read()-1,y=read()-1; val=read(); Modify(x,y,val); break;
                    case 7: x=read()-1,y=read()-1; GetSum(x,y); break;
                    case 8: x=read()-1,y=read()-1; GetRange(x,y); break;
                    case 9: x=read()-1,y=read()-1; GetClose(x,y); break;
                    case 10: x=read()-1,y=read()-1,k=read(); GetKth(x,y,k); break;
                    case 11: x=read()-1,y=read()-1,val=read(); GetSmall(x,y,val); break;
                }
        }
    return 0;
}
还没实现完

 

以上是关于BZOJ-3337ORZJRY I 块状链表的主要内容,如果未能解决你的问题,请参考以下文章

水平居中设置

[NOI2003]Editor(块状链表)

常见的块状元素与内联元素

标签分类

常用的标签分类和嵌套规则

Python数据结构与算法(2.6)——块状链表