题目链接:点这里!!!!
题意:带修改的求区间第K大
题解:
带修改的求区间第K大,很容易想到的一个做法是主席树。
但是注意一下数据的范围,n<=100000。如果用主席树的话,会直接TLE+MLE。
所以主席树在这道题上是不可行的。我们考虑别的做法,我们注意到这道题可以离线处理,基于离线,我们就可以用整体二分来做这道题。
对于一个区间[L,R],我们假设一个数s,求得区间里小于等于s的数的个数为num,如果num>=k,答案肯定小于等于s;如果num<k,答案肯定大于s。
利用这点,我们可以将所有询问一起二分。
我们对所有询问二分答案,然后判断每个询问的答案是否大于当前标准,按照此规定将询问划分成两部分,递归解决。
操作分为三种:
1、给x位置增加一个数v
2、给x位置删除一个数v
3、询问[l,r]中<=mid的数的个数是否<K,mid作为判断的标准。
直接递归就能解决。
如果还有不懂直接看代码吧。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0]C:\Program Files\Git\bin const int MOD = 1000000007; const int N = 1e5+15; const int maxn = 3e5+1000; const int letter = 130; const int INF = 1e17; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; inline 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; } ///N 1e5 ///maxn 3e5 int n,q,a[maxn],tot; int p1[maxn],p2[maxn],ans[maxn]; int c[maxn]; struct node{ int id,l,r,v; ///id -1 +1 2 }qu[maxn]; void addqu(int id,int l,int r,int v){ qu[tot].id=id,qu[tot].l=l,qu[tot].r=r,qu[tot].v=v,p1[tot]=tot++; } int lowbit(int x){ return x&(-x); } void update(int x,int val){ while(x<=n){ c[x]+=val; x+=lowbit(x); } } int getsum(int x){ int ans=0; while(x>0){ ans+=c[x]; x-=lowbit(x); } return ans; } void solve(int L,int R,int low,int high){ if(L>R) return; if(low==high){ while(L<=R){ if(qu[p1[L]].id==2) ans[p1[L]]=low; L++; } return; } int mid=(low+high)/2,j,len; int l=L,r=R; for(int i=L;i<=R;i++){ j=p1[i]; if(qu[j].id==2){ len=getsum(qu[j].r)-getsum(qu[j].l-1); if(len<qu[j].v) qu[j].v-=len,p2[r--]=j; else p2[l++]=j; } else { if(qu[j].v<=mid) update(qu[j].l,qu[j].id),p2[l++]=j; else p2[r--]=j; } } for(int i=L;i<=R;i++){ j=p1[i]; if(qu[j].id!=2&&qu[j].v<=mid) update(qu[j].l,-qu[j].id); } int i=L; for(i=L;i<l;i++)p1[i]=p2[i]; for(r=R;i<=R;r--,i++) p1[i]=p2[r]; solve(L,l-1,low,mid); solve(l,R,mid+1,high); } ///hdu 5412 int main(){ int id,x,y,z; while(scanf("%d",&n)!=EOF){ tot=0; int max1=-1; for(int i=1;i<=n;i++){ scanf("%d",a+i); addqu(1,i,i,a[i]); max1=max(max1,a[i]); } scanf("%d",&q); for(int i=0;i<q;i++){ scanf("%d%d%d",&id,&x,&y); if(id==1){ addqu(-1,x,x,a[x]); a[x]=y; addqu(1,x,x,a[x]); max1=max(max1,y); } else { scanf("%d",&z); addqu(2,x,y,z); } } /// printf("%d\n",max1); solve(0,tot-1,1,max1); for(int i=0;i<tot;i++) { if(qu[i].id==2) { printf("%d\n",ans[i]); } } } return 0; } /* 10 2 100 23 7 2 3 6 3 1 9 7 2 1 10 2 2 1 4 3 1 2 1 2 1 6 1 2 1 10 2 1 4 1000 2 1 9 9 */