Description
Given a sequence a[1],a[2],a[3]... a[n], the program must answer such questions: for a given i,j,k, i n a[i],a[i+1],a[i+2]... What is the number of the smallest K in a[j] (1 < K < j-i+1), and you can change some values of a[i], after which the program can continue to answer the above questions for the changed a. You need to write a program that reads sequence a from the input file and then reads a series of instructions, including inquiry instructions and modification instructions. For each inquiry instruction, you must output the correct answer. The first line has two positive integers n(1 < n < 10000) and m(1 < m < 10000). Represents the length of the sequence and the number of instructions, respectively. The second line has n numbers, representing a[1],a[2]... a[n], these numbers are less than 10 ^ 9. The next M lines describe each instruction in one of the following two formats. Q i j k or C i t Q i j k (i,j,k are numbers, 1 < I < J < n, 1 < K < j-i+1) denotes a n inquiry instruction, asking a[i], a[i+1]... The smallest K in a[j]. CT (1 < I < n, 0 < T < 10 ^ 9) means that a[i] is changed to t.
Input
For each query, you need to output his answer, each output occupies a separate line.
Sample Input
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
HINT
In 20% of the data, m,n are less than 100; in 40% of the data, m,n are less than 1000; in 100% of the data, m,n are less than 10000.
Solution: the whole dichotomy.
Some questions have been done to make a clearer distinction between the division and division of CDQ and the overall dichotomy.
First of all, CDQ divides and conquers the strongest emphasis on a word: time order. That's why it's offline. CDQ divide and conquer is more like a merge, first doing the left, then doing the right, and then processing the left to modify the right query.
But the whole dichotomy is essentially a dichotomy, just a bunch of things. Its operation and answer are divided into two parts at the same time, each time dealing with a certain range of operations, to delimit a more accurate range of the part of the answer, until the correct answer is found.
So there's a big difference between the two.
If the number smaller than mid is larger than k-1, then put it on the left, or put it on the right; if the number of modifications is less than mid, that is, if the number of modifications has an effect on the dichotomy of the left sequence, put it on the left, or put it on the right.
The code is as follows:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define ll long long
#define inf 0x7f7f7f7f
#define N 30005
#define lb(x) (x&(-x))
using namespace std;
ll read()
{
ll x=0,f=1;
char c=getchar();
while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
while(c<='9' && c>='0') {x=x*10+c-'0';c=getchar();}
return x*f;
}
struct nod
{
int op,x,y,k,id,cur;
}q[N],tmp[N];
int n,m,x,y,z,tot,a[N],Count,ans[N],t[N],tmpp[N];
char c[5];
bool mark[N];
void add(int x,int v)
{
while(x<=n)
{
t[x]+=v;
x+=lb(x);
}
}
int query(int x)
{
int ret=0;
while(x)
{
ret+=t[x];
x-=lb(x);
}
return ret;
}
void solve(int l,int r,int L,int R)
{
if(l>r) return ;
if(L==R)
{
for(int i=l;i<=r;i++) if(q[i].op==3) ans[q[i].id]=L;
return ;
}
int mid=(L+R)>>1;
for(int i=l;i<=r;i++)
{
if(q[i].op==1 && q[i].y<=mid) add(q[i].x,1);
else if(q[i].op==2 && q[i].y<=mid) add(q[i].x,-1);
else if(q[i].op==3) tmpp[i]=query(q[i].y)-query(q[i].x-1);
}
for(int i=l;i<=r;i++)
{
if(q[i].op==1 && q[i].y<=mid) add(q[i].x,-1);
else if(q[i].op==2 && q[i].y<=mid) add(q[i].x,1);
}
int cnt=0;
for(int i=l;i<=r;i++)
{
if(q[i].op==3)
{
if(q[i].cur+tmpp[i]>=q[i].k) cnt++,mark[i]=1;
else q[i].cur+=tmpp[i],mark[i]=0;
}
else
{
if(q[i].y<=mid) cnt++,mark[i]=1;
else mark[i]=0;
}
}
int l1=l,l2=l+cnt;
for(int i=l;i<=r;i++)
{
if(mark[i]) tmp[l1++]=q[i];
else tmp[l2++]=q[i];
}
for(int i=l;i<=r;i++) q[i]=tmp[i];
solve(l,l1-1,L,mid);solve(l1,l2-1,mid+1,R);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
q[++tot].op=1;q[tot].x=i;q[tot].y=a[i];q[tot].id=0;
}
for(int i=1;i<=m;i++)
{
scanf("%s",c);
x=read(),y=read();
if(c[0]=='C')
{
q[++tot].op=2;q[tot].x=x;q[tot].y=a[x];q[tot].id=0;
q[++tot].op=1;q[tot].x=x;q[tot].y=y;q[tot].id=0;
a[x]=y;
}
else
{
z=read();
q[++tot].op=3;q[tot].x=x;q[tot].y=y;q[tot].k=z;q[tot].id=++Count;
}
}
solve(1,tot,0,inf);
for(int i=1;i<=Count;i++) printf("%d\n",ans[i]);
return 0;
}