【清华集训2017模拟】Sequence
2017-09-04 20:32
477 查看
Description
Input
Output
共m行,每行一个整数表示询问的答案Sample Input
105 4 8 9 1 6 3 2 7 10
5 6 3 4 1 2 10 7 8 9
5
3 7 2 4 1
3 10 3 7 4
6 8 1 3 1
9 10 2 2 1
2 3 2 2 1
Sample Output
28
2
9
3
Solution
这题一看到题就有一种很显然的做法,简单来说就是分块套分块套分块,然而编程复杂度太高稍微分析一下就会发现,如果以原顺序为一维,第一关键字为二维,第二关键字为权值,那么那些点都可以抽象成一个二维平面内的点,询问就是询问一个矩形内权值第几的点的权值
那么显然可以用树套树来做,然而我不会
所以可以用一种更简单的方法:整体二分
这是我第一次打整体二分,所以可能有点难看
思想就是,每次二分出的mid,然后对每个询问判断这个询问的答案比mid大还是比mid小,分为两部分并继续二分
那么在这题中,如果将询问和点都按照第一维来排序,依次操作,如果是点就加入数据结构中,查询就用关键字直接查询。
那么数据结构中有的就是第一维被压扁,只有第二维的值了
在查询矩形时,就可以变为查询区间,矩形的左右两个相减,就可以只需要一个一维的数据结构,查询点数,用树状数组就可以维护了
可能说不清楚,自行看看标吧
Code
#include<cstdio> #include<algorithm> #include<cstring> #define fo(i,a,b) for(int i=a;i<=b;i++) #define N 3010000 #define lowbit(x) ((x)&(-x)) using namespace std; struct node{ int x,y,z,i,q,w,k; }a ,c ,d ; struct note{ int l,r,d; }t ; int n,m,tot,b ,ans ,ta ; bool cnt(node x,node y){return x.z<y.z||(x.z==y.z&&x.q<y.q);} void ins(int v,int i,int j,int x) { t[v].d++;if(i==j) return; int m=(i+j)/2; if(x<=m) t[++tot]=t[t[v].l],t[v].l=tot,ins(t[v].l,i,m,x); else t[++tot]=t[t[v].r],t[v].r=tot,ins(t[v].r,m+1,j,x); } int get(int v1,int v2,int i,int j,int x) { if(i==j) return i; int m=(i+j)/2; if(t[t[v2].l].d-t[t[v1].l].d>=x) return get(t[v1].l,t[v2].l,i,m,x); else return get(t[v1].r,t[v2].r,m+1,j,x-t[t[v2].l].d+t[t[v1].l].d); } void add(int x,int y) { for(;x<=n;x+=lowbit(x)) ta[x]+=y; } int que(int x) { int ans=0; for(;x;x-=lowbit(x)) ans+=ta[x]; return ans; } void dg(int q,int w,int l,int r) { if(l==r) { fo(i,q,w) if(a[i].q) ans[a[i].i]=l; return; } int mid=(l+r)/2; int t1=0,t2=0; fo(i,q,w) if(a[i].q) b[a[i].i]+=(que(a[i].y)-que(a[i].x-1))*a[i].w; else if(a[i].x<=mid) add(a[i].y,1); fo(i,q,w) if(a[i].q) { if(b[a[i].i]>=a[i].k) c[++t1]=a[i]; else d[++t2]=a[i],d[t2].k-=b[a[i].i]; } else { if(a[i].x<=mid) c[++t1]=a[i]; else d[++t2]=a[i]; } fo(i,q,w) if(a[i].q) b[a[i].i]=0; else if(a[i].x<=mid) add(a[i].y,-1); fo(i,1,t1) a[q+i-1]=c[i]; fo(i,1,t2) a[q+t1+i-1]=d[i]; dg(q,q+t1-1,l,mid); dg(q+t1,w,mid+1,r); } int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); scanf("%d",&n);tot=n; fo(i,1,n) scanf("%d",&a[i].y),a[i].z=i,a[i].q=0,t[i]=t[i-1],ins(i,1,n,a[i].y); fo(i,1,n) scanf("%d",&a[i].x); tot=n; scanf("%d",&m); fo(i,1,m) { int l,r,x,y,k;scanf("%d%d%d%d%d",&l,&r,&x,&y,&k); x=get(l-1,r,1,n,x);y=get(l-1,r,1,n,y); a[++tot].q=1;a[tot].z=l-1;a[tot].x=x;a[tot].y=y;a[tot].i=i;a[tot].w=-1;a[tot].k=k; a[++tot].q=1;a[tot].z=r;a[tot].x=x;a[tot].y=y;a[tot].i=i;a[tot].w=1;a[tot].k=k; } sort(a+1,a+tot+1,cnt); dg(1,tot,1,n); fo(i,1,m) printf("%d\n",ans[i]); }
相关文章推荐
- 【清华集训2017模拟】Sequence
- 【JZOJ5296】【清华集训2017模拟】Sequence
- 【JZOJ 5296】【清华集训2017模拟】Sequence
- [JZOJ5498]【清华集训2017模拟12.10】大佬的难题
- JZOJ 5483. 【清华集训2017模拟11.26】简单路径
- 【清华集训2017模拟11.26】字符串
- JZOJ 5489. 【清华集训2017模拟11.28】海明距离
- 【JZOJ5295】【清华集训2017模拟】Create
- [JZOJ5500]【清华集训2017模拟12.10】营养餐
- 【JZOJ 5276】【清华集训2017模拟】神奇的玩具
- jzoj5317 【清华集训2017模拟8.19】func (寻找性质)
- 【JZOJ5296】【清华集训模拟】Sequence(整体二分)
- 5483. 【清华集训2017模拟11.26】简单路径
- JZOJ5489. 【清华集训2017模拟11.28】海明距离
- [jzoj]5484. 【清华集训2017模拟11.26】快乐树(树形DP)
- 【清华集训 2017】小Y的地铁 [模拟退火]
- JZOJ 5489. 【清华集训2017模拟11.28】海明距离
- JZOJ 5500. 【清华集训2017模拟12.10】营养餐
- 【清华集训2017模拟12.09】塔
- 5296. 【清华集训2017模拟】Sequence 树套树