이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define ll int
#define itr ::iterator
typedef pair<int,int> pii;
const int MAX=3e6;
pii blocks[MAX];
int ROOT,SizeOfBlock,dp[MAX],BlockNumber[MAX],Index[1100][1100];
int N,K,qcnt,ptr,start,pos[MAX],nxt[MAX],pre[MAX],covered[MAX],arr[MAX];
void recalculate(ll idx)
{
int start_=blocks[idx].first,end_=blocks[idx].second,lol=start_,lop=1;
pre[start_]=0;
Index[idx][1]=start_;
for(int A=nxt[start_];A!=nxt[end_];A=nxt[A])
{
pre[A]=lol;
lol=A;
Index[idx][++lop]=A;
}
for(int A=lop+1;Index[idx][A]>0;A++)
Index[idx][A]=0;
int cov=end_,cnt=1,ptr1=end_;
for(int A=end_;A>0;A=pre[A])
{
if(arr[cov]-arr[A]>K)
{
cov=A;
++cnt;
}
dp[A]=cnt;
if(dp[A]==1)
covered[A]=arr[A]+K;
else
{
while(arr[pre[ptr1]]-arr[A]>K)
ptr1=pre[ptr1];
covered[A]=covered[ptr1];
}
}
return ;
}
void build()
{
SizeOfBlock=0;
ll lol=0;
for(int A=0;A<=ROOT;A++)
for(int B=0;Index[A][B]>0;B++)
Index[A][B]=0;
for(int A=start;A>0;A=nxt[A])
{
BlockNumber[A]=SizeOfBlock;
Index[BlockNumber[A]][++lol]=A;
if(lol==ROOT or nxt[A]==0)
{
blocks[SizeOfBlock++]=mp(Index[BlockNumber[A]][1],A);
lol=0;
}
}
for(int A=0;A<SizeOfBlock;A++)
recalculate(A);
return ;
}
void remove(ll idx,ll val)
{
if(idx==start)
{
start=nxt[start];
blocks[0].first=start;
recalculate(BlockNumber[idx]);
return ;
}
for(int A=blocks[BlockNumber[idx]].first;nxt[A]>0;A=nxt[A])
{
if(A==idx)
{
A=blocks[BlockNumber[idx]-1].second;
assert(nxt[A]==idx);
}
if(nxt[A]==idx)
{
nxt[A]=nxt[nxt[A]];
if(idx==blocks[BlockNumber[idx]].first)
blocks[BlockNumber[idx]].first=nxt[A];
else if(idx==blocks[BlockNumber[idx]].second)
blocks[BlockNumber[idx]].second=A;
break;
}
}
recalculate(BlockNumber[idx]);
return ;
}
void insert(ll idx,ll val)
{
if(val<=arr[start])
{
nxt[idx]=start;
start=idx;
BlockNumber[idx]=0;
blocks[0].first=start;
recalculate(BlockNumber[idx]);
}
else
{
ll lol=start;
for(int A=start;A>0;A=nxt[A])
if(val>=arr[A])
lol=A;
nxt[idx]=nxt[lol];
nxt[lol]=idx;
BlockNumber[idx]=BlockNumber[lol];
if(lol==blocks[BlockNumber[lol]].second)
blocks[BlockNumber[lol]].second=idx;
recalculate(BlockNumber[idx]);
}
/*else
{
int low=0,high=SizeOfBlock-1,mid,res=0,lol=0;
while(low<=high)
{
mid=(low+high)/2;
if(val>=arr[blocks[mid].first])
res=mid,low=mid+1;
else
high=mid-1;
}
assert(val>=arr[blocks[res].first]);
for(int A=blocks[res].first;A!=nxt[blocks[res].second];A=nxt[A])
{
if(arr[A]<=val)
lol=A;
if(arr[A]==A)
break;
}
nxt[idx]=nxt[lol];
nxt[lol]=idx;
BlockNumber[idx]=BlockNumber[lol];
if(lol==blocks[BlockNumber[lol]].second)
blocks[BlockNumber[lol]].second=idx;
recalculate(BlockNumber[idx]);
}*/
return ;
}
ll count(ll CurrentBlock,ll CoveredTill)
{
if(CurrentBlock>=SizeOfBlock)
return 0;
ll low=1,high=ROOT+1,mid,res=-1;
while(low<=high)
{
mid=(low+high)/2;
if(Index[CurrentBlock][mid]==0)
high=mid-1;
else if(arr[Index[CurrentBlock][mid]]<=CoveredTill)
res=Index[CurrentBlock][mid],
low=mid+1;
else
high=mid-1;
}
if(res==blocks[CurrentBlock].second)
return count(CurrentBlock+1,CoveredTill);
else if(res<0)
res=blocks[CurrentBlock].first;
else
res=nxt[res];
return dp[res]+count(CurrentBlock+1,covered[res]);
}
void init(int n,int l,int X[])
{
N=n;
K=l;
ptr=n;
start=1;
ROOT=sqrt(n)+1;
for(int A=1;A<=N;A++)
{
pos[A]=A;
nxt[A]=A+1;
arr[A]=X[A-1];
}
nxt[N]=0;
build();
return ;
}
int update(int i,int y)
{
if(N==1)
return 1;
++i;
++ptr;
++qcnt;
remove(pos[i],y);
pos[i]=ptr;
arr[ptr]=y;
insert(pos[i],y);
if(qcnt%ROOT==0)
{
qcnt=0;
build();
}
return count(0,-1);
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |