回转寿司
来源:互联网 发布:加拿大大学预科知乎 编辑:程序博客网 时间:2024/04/19 15:04
题目描述
分块
你考虑有一堆人,价格为x的进去了出来会变成啥样。
那么肯定是找到这堆人所持价格的最大值y,如果x>y,出来的还是y,否则x会变成某个人手里的,然后出来的是y。
我们考虑分块,每个块维护一个数堆。
如果x要经过一个块,可以丢进数堆,再取出一个最大值。然后还要给这个块打上一个标记。
但是对于零散的不是很好做,即重构块,我们如何快速得到每个位置经过一系列标记后的值?
注意这个问题具有高度对称性,即一盘寿司一盘寿司的经过人,可以看做一个一个人走过寿司。
对标记也维护堆,然后枚举每个人,它手里的是x,那么把x丢进标记堆,再取出一个最小值,就是这个人更新后的。
堆要手打。
标记只在重构块时才丢进堆中,而且丢进堆前先排序。
一个块如果没有标记可以不重构。
一个x经过一个块如果还是x那么不给这个块打标记。
加上上述优化来卡常。
#include<cstdio>#include<algorithm>#include<queue>#include<vector>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=400000+10,maxq=25000+10,B=633;//priority_queue<int> tt[B+10],num[B+10];//num big tt smallint tt[B+10][maxq],num[B+10][B+10],zt[B+10],zn[B+10];int bj[B+10][maxq],zb[B+10];int a[maxn],belong[maxn];int i,j,k,l,r,x,y,t,n,m,tot;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;}void push1(int x,int v){ tot=zn[x]; num[x][++tot]=v; int k=tot; while (k>1){ if (num[x][k]>num[x][k/2]) swap(num[x][k],num[x][k/2]); else break; k/=2; } zn[x]=tot;}int pop1(int x){ int t=num[x][1]; tot=zn[x]; num[x][1]=num[x][tot]; tot--; int k=1,j; while (k*2<=tot){ if (k*2+1>tot||num[x][k*2]>num[x][k*2+1]) j=k*2;else j=k*2+1; if (num[x][k]<num[x][j]) swap(num[x][k],num[x][j]); else break; k=j; } zn[x]=tot; return t;}void push2(int x,int v){ tot=zt[x]; tt[x][++tot]=v; int k=tot; while (k>1){ if (tt[x][k]<tt[x][k/2]) swap(tt[x][k],tt[x][k/2]); else break; k/=2; } zt[x]=tot;}int pop2(int x){ int t=tt[x][1]; tot=zt[x]; tt[x][1]=tt[x][tot]; tot--; int k=1,j; while (k*2<=tot){ if (k*2+1>tot||tt[x][k*2]<tt[x][k*2+1]) j=k*2;else j=k*2+1; if (tt[x][k]>tt[x][j]) swap(tt[x][k],tt[x][j]); else break; k=j; } zt[x]=tot; return t;}void rebuild(int x){ if (zb[x]==0){ zt[x]=zn[x]=0; return; } int i,t; sort(bj[x]+1,bj[x]+zb[x]+1); fo(i,1,zb[x]) push2(x,bj[x][i]); zb[x]=0; fo(i,(x-1)*B+1,min(x*B,n)){ push2(x,a[i]); //tt[x].push(-a[i]); a[i]=pop2(x); /*a[i]=-tt[x].top(); tt[x].pop();*/ } zt[x]=zn[x]=0; /*while (!tt[x].empty()) tt[x].pop(); while (!num[x].empty()) num[x].pop();*/}int main(){ freopen("sushi.in","r",stdin);freopen("sushi.out","w",stdout); n=read();m=read(); fo(i,1,n){ a[i]=read(); belong[i]=(i-1)/B+1; push1(belong[i],a[i]); //num[belong[i]].push(a[i]); } while (m--){ j=read();k=read();x=read(); l=belong[j];r=belong[k]; if (l==r&&j<=k){ rebuild(l); //if (j<k){ fo(i,j,k) if (x<a[i]) swap(x,a[i]); //} /*else{ fo(i,j,min(l*B,n)) if (x<a[i]) swap(x,a[i]); fo(i,(l-1)*B+1,k) if (x<a[i]) swap(x,a[i]); }*/ fo(i,(l-1)*B+1,min(l*B,n)) { push1(l,a[i]); //num[l].push(a[i]); } printf("%d\n",x); continue; } rebuild(l); fo(i,j,min(l*B,n)) if (x<a[i]) swap(x,a[i]); fo(i,(l-1)*B+1,min(l*B,n)){ push1(l,a[i]); //num[l].push(a[i]); } l=l%belong[n]+1; while (l!=r){ push1(l,x); //num[l].push(x); y=pop1(l); /*x=num[l].top(); num[l].pop();*/ if (y!=x){ bj[l][++zb[l]]=x; //push2(l,x); //tt[l].push(-x); x=y; } l=l%belong[n]+1; } rebuild(r); fo(i,(r-1)*B+1,k) if (x<a[i]) swap(x,a[i]); fo(i,(r-1)*B+1,min(r*B,n)){ push1(r,a[i]); //num[r].push(a[i]); } printf("%d\n",x); }}
阅读全文
0 0
- 回转寿司
- BZOJ4627 [BeiJing2016]回转寿司
- 4627: [BeiJing2016]回转寿司
- Bzoj4627: [BeiJing2016]回转寿司
- Bzoj4627:BeiJing2016-回转寿司
- 【BZOJ】4627 [BeiJing2016]回转寿司
- 【NOI2017模拟6.23】回转寿司
- [BZOJ4627][BeiJing2016]回转寿司 cdq分治
- bzoj 4627: [BeiJing2016]回转寿司 线段树
- BZOJ 4627回转寿司(值域线段树)
- BZOJ4627 回转寿司(值域线段树)
- 【线段树】【CDQ分治】回转寿司
- BZOJ 4627: [BeiJing2016]回转寿司 cdq
- BZOJ 4627: [BeiJing2016]回转寿司【前缀和,值域线段树
- bzoj 4627 回转寿司(权值线段树)
- bzoj-4627 [BeiJing2016]回转寿司 hash+权值线段树
- 寿司?
- 回转一下
- Java并发编程-活跃度问题
- LeetCode --Reverse Integer
- 一个神奇高效的工具-正则表达式(三)
- 2743:字符串判等
- Team Foundation Server 2012 安装配置过程和注意事项
- 回转寿司
- 面试题32:从1到n整数中1出现的次数
- Java面试题总结
- Godfather POJ
- 优先队列 c++ 函数的使用方法
- web前端总结(一)
- echarts功能键如何添加
- POJ 2401 Street Polygon 笔记
- LeetCode----240. Search a 2D Matrix II (M)