JZOJ 5431. 【NOIP2017提高A组集训10.28】序列操作
2017-10-29 22:12
423 查看
Description
一开始有n个非负整数hi,接下来会进行m次操作,第i次操作给出一个数c[i],要求你选出c[i]个大于零的数并将它们减去1。问最多可以进行多少轮操作后无法操作(即没有c[i]个大于零的数)
Input
第一行两个数表示n和m第二行n个数描述h[i]
第三行m个数描述c[i]
Output
一行表示答案,即最多可以进行多少轮操作后无法操作Sample Input
输入1:
3 51 2 5
1 2 3 2 1
输入2:
5 51 3 3 4 5
1 2 4 4 4
Sample Output
输出1:
3输出2:
5Data Constraint
对于10%的数据满足,1<=n,m<=5对于另外20%的数据满足,1<=n<=8,1<=h[i]<=7
对于50%的数据满足,1<=n,m<=1000
对于80%的数据满足,1<=n,m<=100000
对于100%的数据满足,1<=n,m<=1000000
Solution
虽然数据有点大,还是决定线段树……显然,选择的 c 个数一定选最大的那 c 个。
为了方便处理,先把数组排序,中途维护时也保证单调。
区间减,如果第 n−c+1 个数属于一段相同的数,就把相同的那段移到前面减(保证单调)。
时间复杂度 O(N log N) 。
Code
#include<cstdio> #include<algorithm> using namespace std; const int N=1e6+2; struct data { int mx,c; }f[N<<2]; int ans; int a ; inline int read() { int X=0,w=1; char ch=0; while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar(); return X*w; } inline int max(int x,int y) { return x>y?x:y; } inline void modify(int v) { if(f[v].c) { int ls=v<<1,rs=ls|1; f[ls].c+=f[v].c; f[rs].c+=f[v].c; f[ls].mx-=f[v].c; f[rs].mx-=f[v].c; f[v].c=0; } } inline void make(int v,int l,int r) { if(l==r) { f[v].mx=a[l]; return; } int mid=(l+r)>>1; make(v<<1,l,mid); make(v<<1|1,mid+1,r); f[v].mx=max(f[v<<1].mx,f[v<<1|1].mx); } inline void change(int v,int l,int r,int x,int y) { if(l==x && r==y) { f[v].c++; f[v].mx--; return; } modify(v); int mid=(l+r)>>1; if(y<=mid) change(v<<1,l,mid,x,y); else if(x>mid) change(v<<1|1,mid+1,r,x,y); else { change(v<<1,l,mid,x,mid); change(v<<1|1,mid+1,r,mid+1,y); } f[v].mx=max(f[v<<1].mx,f[v<<1|1].mx); } inline int findnum(int v,int l,int r,int x) { modify(v); if(l==r) return f[v].mx; int mid=(l+r)>>1; int t=x<=mid?findnum(v<<1,l,mid,x):findnum(v<<1|1,mid+1,r,x); f[v].mx=max(f[v<<1].mx,f[v<<1|1].mx); return t; } inline int findpos(int v,int l,int r,int x) { modify(v); if(l==r) return l; int mid=(l+r)>>1; int t=f[v<<1].mx>=x?findpos(v<<1,l,mid,x):findpos(v<<1|1,mid+1,r,x); f[v].mx=max(f[v<<1].mx,f[v<<1|1].mx); return t; } int main() { int n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+1+n); make(1,1,n); for(ans=0;ans<m;ans++) { int x=read(),t=findnum(1,1,n,n-x+1); if(t<=0) break; int pos2=findpos(1,1,n,t); if(pos2<n-x+1) { int pos1=findpos(1,1,n,t+1); if(pos1<=n && findnum(1,1,n,pos1)<=t) pos1++; if(pos1<=n) change(1,1,n,pos1,n); if(pos2+pos1-(n-x+1)-1<=n && pos2+pos1-(n-x+1)-1>=pos2) change(1,1,n,pos2,pos2+pos1-(n-x+1)-1); }else change(1,1,n,n-x+1,n); } printf("%d",ans); return 0; }
相关文章推荐
- 【JZOJ5431】【NOIP2017提高A组集训10.28】序列操作
- 【JZOJ 5431】【NOIP2017提高A组集训10.28】序列操作
- JZOJ5431. 【NOIP2017提高A组集训10.28】序列操作
- 【JZOJ 5433】【NOIP2017提高A组集训10.28】图
- [置顶] 【JZOJ5433】【NOIP2017提高A组集训10.28】图
- 【JZOJ 5432】【NOIP2017提高A组集训10.28】三元组
- JZOJ 5432. 【NOIP2017提高A组集训10.28】三元组
- 【JZOJ5432】【NOIP2017提高A组集训10.28】三元组
- JZOJ 5417. 【NOIP2017提高A组集训10.24】方阵
- JZOJ 5419. 【NOIP2017提高A组集训10.24】筹备计划
- [JZOJ5436]【NOIP2017提高A组集训10.30】Group
- JZOJ 5434. 【NOIP2017提高A组集训10.30】Matrix
- JZOJ 5408. 【NOIP2017提高A组集训10.21】Dark
- 【JZOJ 5414】【NOIP2017提高A组集训10.22】幸运值
- 【JZOJ5410】【NOIP2017提高A组集训10.22】小型耀斑
- 【JZOJ 5426】【NOIP2017提高A组集训10.25】摘Galo
- JZOJ5428. 【NOIP2017提高A组集训10.27】查询
- JZOJ5438. 【NOIP2017提高A组集训10.31】Tree
- JZOJ 5436. 【NOIP2017提高A组集训10.30】Group
- 【JZOJ 5410】【NOIP2017提高A组集训10.22】小型耀斑