BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 418 Solved: 235
[ Submit][ Status][ Discuss]
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
HINT
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中abs(c)<=Maxlongint
Source
本来上一次就偷懒。。。、
话说写线段树不写离散化可不是一个好习惯。。。
所以我果断加上了离散。。。
================Cute 分割线 ============================
其实这题可以直接拆数,zkw线段树区间修改法解决数组修改。。。
但是做到一半就把自己绕晕了....我X注定NC
话说这题要离散的是插入的数——所以拆的于是插入的数(具体来说,S1:头尾插1个,S2:头尾差x*i个)
然后总算A了……
我的人生都浪费在DeBug上了么......
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #include<cmath> #include<cctype> #include<map> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,n) for(int i=n;i;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define RepD(i,n) for(int i=n;i>=0;i--) #define MEM(a) memset(a,0,sizeof(a)) #define MEMI(a) memset(a,127,sizeof(a)) #define MEMi(a) memset(a,128,sizeof(a)) #define MAXN (50000+10) #define MAXM (50000+10) #define MINAi (1) #define MAXAi (size) #define maxlongint (2147483647) int n,m; int a2[MAXN],size=0; struct node { int ch[2],c; node():c(0){ch[0]=ch[1]=0;} }q[10000000]; int root[MAXN<<1],tail=0; void inc(int &x,long long l,long long r,int c,int d) { if (!x) x=++tail; q[x].c+=d; if (l==r) return; long long m=l+r>>1; if (c<=m) inc(q[x].ch[0],l,m,c,d); else inc(q[x].ch[1],m+1,r,c,d); } void update(int x,int c,int d) { for(int i=x;i<=n;i+=i&(-i)) inc(root[i],MINAi,MAXAi,c,d); for(int i=x;i<=n;i+=i&(-i)) inc(root[i+n],MINAi,MAXAi,c,d*x); } int ans[MAXN][2],ans_end[2],ans_siz[2]; void qur(int x) { Rep(p,2) for(int i=x;i;i-=i&(-i)) ans[++ans_siz[p]][p]=root[i+p*n]; } void turn(bool c) { Rep(p,2) For(i,ans_siz[p]) ans[i][p]=q[ans[i][p]].ch[c]; } struct comm { int p,a,b,c; comm(){} }ask[MAXM]; map<long long ,int> h; int main() { // freopen("bzoj3110.in","r",stdin); // freopen(".out","w",stdout); scanf("%d%d",&n,&m); For(i,m) {scanf("%d%d%d%d",&ask[i].p,&ask[i].a,&ask[i].b,&ask[i].c);if (ask[i].p==1) a2[++size]=ask[i].c;} sort(a2+1,a2+1+size); size=unique(a2+1,a2+1+size)-(a2+1); For(i,size) h[a2[i]]=i; For(i,m) { if (ask[i].p==1) ask[i].c=h[ask[i].c]; } For(i,m) { int p; p=ask[i].p; if (p==1) { int l,r,c; l=ask[i].a,r=ask[i].b,c=ask[i].c; update(l,c,1);update(r+1,c,-1); } else { long long l,r,k,l1,r1; l=ask[i].a,r=ask[i].b,k=ask[i].c;l1=l,r1=r; ans_siz[0]=ans_siz[1]=0; qur(r);memcpy(ans_end,ans_siz,sizeof(ans_end));qur(l-1); l=MINAi,r=MAXAi; while (l<r) { long long s[2]={0},m=(l+r)>>1; Rep(p,2) { For(i,ans_end[p]) s[p]+=q[q[ans[i][p]].ch[1]].c; long long p1=s[p];s[p]=0; Fork(i,ans_end[p]+1,ans_siz[p]) s[p]+=q[q[ans[i][p]].ch[1]].c; if (p==0) s[p]=p1*(r1+1)-s[p]*l1; else s[p]=p1-s[p]; } long long tot=s[0]-s[1]; // cout<<tot<<' '; if (k<=tot) l=m+1,turn(1);else r=m,k-=tot,turn(0); } printf("%d\n",a2[l]); } } return 0; }