bzoj 3337: ORZJRY I (块状链表)

来源:互联网 发布:美国情景喜剧排行知乎 编辑:程序博客网 时间:2024/06/08 15:16

3337: ORZJRY I

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 188  Solved: 48
[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

[Submit][Status][Discuss]

题解:块状链表。


#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#define N 10000#define LL long long#define inf 10000000000LLusing namespace std;int n,m,line[N],blocksize,st[N];struct node{int d[1003],s[1003];int rev,delta,same,size,next;LL sum;}a[N];queue<int> p;void clear(int t){a[t].sum=a[t].same=a[t].size=a[t].rev=a[t].delta=0;}int newnode(){int temp=p.front(); p.pop();return temp;}int del(int t){p.push(t); clear(t);}void init(){for (int i=1;i<N;i++) p.push(i);a[0].next=-1; a[0].size=0;}void pushdown(int t){if (a[t].rev) { a[t].rev=0; for (int i=1;i<=a[t].size;i++)  line[i]=a[t].d[i]; for (int i=a[t].size;i>=1;i--)  a[t].d[a[t].size-i+1]=line[i]; }if (a[t].same){for (int i=1;i<=a[t].size;i++) a[t].d[i]=a[t].same;a[t].sum=a[t].same*a[t].size;    a[t].same=0;}if (a[t].delta){for (int i=1;i<=a[t].size;i++) a[t].d[i]+=a[t].delta;a[t].sum+=a[t].size*a[t].delta;a[t].delta=0;}}void update(int x){a[x].sum=0;for (int i=1;i<=a[x].size;i++) a[x].sum+=a[x].d[i],a[x].s[i]=a[x].d[i];sort(a[x].s+1,a[x].s+a[x].size+1);}void merge(int x){int k=a[x].next;pushdown(x); pushdown(k);for (int i=1;i<=a[k].size;i++) a[x].d[++a[x].size]=a[k].d[i];a[x].next=a[k].next; del(k);update(x);}void maintain(int now){for (;now!=-1;now=a[now].next) if (a[now].next!=-1&&a[now].size+a[a[now].next].size<=blocksize)  merge(now);}void find(int &pos,int &now){for (now=0;a[now].next!=-1&&pos>a[now].size;now=a[now].next) pos-=a[now].size;}void spilt(int now,int pos){pushdown(now); int t=newnode();for (int i=pos;i<=a[now].size;i++) a[t].d[++a[t].size]=a[now].d[i];a[t].next=a[now].next; a[now].next=t; a[now].size=max(pos-1,0);update(t); update(now);}void insert(int pos,int val){int now; pos++;find(pos,now); spilt(now,pos);a[now].d[++a[now].size]=val;update(now);maintain(now);}void erase(int pos){int now;find(pos,now); pushdown(now);     for (int i=pos+1;i<=a[now].size;i++)     a[now].d[i-1]=a[now].d[i];    a[now].size--;update(now);maintain(now);}void solve(int l,int r,int &lp,int &rp){int pos=l;find(pos,lp); spilt(lp,pos); pos=r+1; find(pos,rp); spilt(rp,pos);pos=r;find(pos,rp);}void do_reverse(int l,int r){int lp,rp;solve(l,r,lp,rp);int now=lp;int top=0;for (int i=a[lp].next;i!=a[rp].next;i=a[i].next) st[++top]=i,a[i].rev^=1;a[st[1]].next=a[rp].next;for (int i=top;i>1;i--) a[st[i]].next=st[i-1];a[lp].next=rp;maintain(lp);}void do_move(int l,int r,int k){int lp,mp,rp,np;solve(l,r-k,lp,mp);solve(r-k+1,r,mp,rp);np=a[lp].next;a[lp].next=a[mp].next;a[mp].next=a[rp].next;a[rp].next=np;maintain(lp);}void add(int l,int r,int val){int lp,rp;solve(l,r,lp,rp);int now;for (now=a[lp].next;now!=a[rp].next;now=a[now].next) { a[now].delta+=val; a[now].sum+=a[now].size*val; }maintain(lp);}void same(int l,int r,int val){int lp,rp,now;solve(l,r,lp,rp);for (now=a[lp].next;now!=a[rp].next;now=a[now].next){a[now].delta=0;a[now].same=val;a[now].sum=a[now].size*val;}maintain(lp);}LL qjsum(int l,int r){int lp,rp;solve(l,r,lp,rp);LL ans=0;int now;for (now=a[lp].next;now!=a[rp].next;now=a[now].next)     ans+=a[now].sum;    maintain(lp);    return ans;}int range(int l,int r){int lp,rp;solve(l,r,lp,rp);int maxn=-inf,minn=inf;for (int now=a[lp].next;now!=a[rp].next;now=a[now].next) if (a[now].size!=0)  if (a[now].same)   {   minn=min(minn,a[now].same+a[now].delta);   maxn=max(maxn,a[now].same+a[now].delta);   }  else   {   minn=min(minn,a[now].s[1]+a[now].delta);   maxn=max(maxn,a[now].s[a[now].size]+a[now].delta);   }maintain(lp);return maxn-minn;}int near(int l,int r,int val){int lp,rp;solve(l,r,lp,rp);int ans=inf;for (int now=a[lp].next;now!=a[rp].next;now=a[now].next) if (a[now].same)  ans=min(ans,abs(val-a[now].same-a[now].delta)); else { int id=lower_bound(a[now].s+1,a[now].s+a[now].size+1,val-a[now].delta)-a[now].s; if (id!=a[now].size+1)  ans=min(ans,a[now].s[id]+a[now].delta-val); if (id!=1)  id--,ans=min(ans,val-a[now].s[id]-a[now].delta); }maintain(lp);return ans;}int ask_mink(int l,int r,int k) {int lp,rp;solve(l,r,lp,rp);int ans=0,ll=0,rr=inf;while (ll<rr)    {    int mid=(ll+rr)/2+1;    ans=1;    for (int now=a[lp].next;now!=a[rp].next;now=a[now].next)     if (a[now].same)     {      if (a[now].same+a[now].delta<mid)       ans+=a[now].size;         }         else         {         int id=upper_bound(a[now].s+1,a[now].s+a[now].size+1,mid-a[now].delta-1)-a[now].s;         ans+=max(0,id-1);          }        if (k>=ans)  ll=mid;        else rr=mid-1;    }    maintain(lp);    return ll;}int ask_smaller(int l,int r,int val){int lp,rp; solve(l,r,lp,rp);int ans=0;for (int now=a[lp].next;now!=a[rp].next;now=a[now].next) if (a[now].same)  {  if (a[now].same+a[now].delta<val)   ans+=a[now].size;  }  else  {  int id=upper_bound(a[now].s+1,a[now].s+a[now].size+1,val-a[now].delta-1)-a[now].s;  ans+=id-1;  }maintain(lp); return ans;}int main(){scanf("%d",&n); blocksize=sqrt(n);init();for (int i=1;i<=n;i++) { int x; scanf("%d",&x); insert(i-1,x); }scanf("%d",&m);for (int i=1;i<=m;i++){int op; int x,y,z;scanf("%d",&op);switch(op){case 1:scanf("%d%d",&x,&y); insert(x,y); break;case 2:scanf("%d",&x); erase(x); break;case 3:scanf("%d%d",&x,&y); do_reverse(x,y); break;case 4:scanf("%d%d%d",&x,&y,&z); do_move(x,y,z); break;case 5:scanf("%d%d%d",&x,&y,&z); add(x,y,z); break;case 6:scanf("%d%d%d",&x,&y,&z); same(x,y,z); break;case 7:scanf("%d%d",&x,&y); printf("%lld\n",qjsum(x,y)); break;case 8:scanf("%d%d",&x,&y); printf("%d\n",range(x,y)); break;case 9:scanf("%d%d%d",&x,&y,&z); printf("%d\n",near(x,y,z)); break;case 10:scanf("%d%d%d",&x,&y,&z); printf("%d\n",ask_mink(x,y,z)); break;case 11:scanf("%d%d%d",&x,&y,&z); printf("%d\n",ask_smaller(x,y,z)); break;}/*for (int j=0;;j=a[j].next) { for (int k=1;k<=a[j].size;k++)  cout<<a[j].d[k]<<" "; cout<<"!"<<a[j].rev<<" "; if (a[j].next==-1) break; }cout<<endl;*/}return 0;}



数据生成器:

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<cstdlib>#include<ctime>using namespace std;int main(){freopen("a.in","w",stdout);int n=100000;  cout<<n<<endl; srand(time(0));for (int i=1;i<=n;i++) cout<<rand()%10<<" ";cout<<endl;int m=100000; cout<<m<<endl;for (int i=1;i<=m;i++){int op=rand()%11+1; cout<<op<<" ";int x=rand()%n+1; int y=rand()%n+1; if (x>y) swap(x,y);  int z=rand()%n+1;switch(op){case 1:printf("%d %d\n",x,y); n++; break;case 2:printf("%d\n",x); n--; break;case 3:printf("%d %d\n",x,y); break;case 4:if (y-x==0) if (y!=n) y++;            else x--; printf("%d %d %d\n",x,y,z%(y-x)+1); break;case 5:printf("%d %d %d\n",x,y,z); break;case 6:printf("%d %d %d\n",x,y,z); break;case 7:printf("%d %d\n",x,y); break;case 8:printf("%d %d\n",x,y); break;case 9:printf("%d %d %d\n",x,y,z); break;case 10:printf("%d %d %d\n",x,y,z%(y-x+1)+1); break;case 11:printf("%d %d %d\n",x,y,z); break;}}}


0 0
原创粉丝点击