这道题的线段树做法很是奇巧,正常考试中那种维护的方式还是比较难想到,所以说我先是用分块做的。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=110000;
int n,m,siz,ans,pre,l,q,r,mid;
int t[1000],s[1000],h[maxn],p[1000][1000];
bool cmp(int a,int b){
return (a==0)?h[b]>0:(long long)h[a]*b<(long long)h[b]*a;
}
int main(){
scanf("%d%d",&n,&m),n++;
siz=(int)(0.5*sqrt(n*log(1.0*n)/log(2.0)));
for(register int a,b,i=1;i<=m;i++){
scanf("%d%d",&a,&b);
h[a]=b,p[a/siz][0]=0;
for(register int j=a/siz*siz;j<(a/siz+1)*siz;j++)
if(cmp(p[a/siz][p[a/siz][0]],j))p[a/siz][++p[a/siz][0]]=j;
for(ans=pre=q=0;q*siz<n;q++){
l=1,r=p[q][0]+1;
while(l<r){
mid=(l+r)>>1;
if(cmp(pre,p[q][mid]))r=mid;
else l=mid+1;
}
ans+=p[q][0]+1-r;
if(p[q][0]>=l)pre=p[q][p[q][0]];
}
printf("%d\n",ans);
}
return 0;
}
代码极其少,并且特别好理解。只是分块时所分的块的大小跟平时的 n√ 不同。而是 12n∗logn2−−−−−−√ ,这种分块方法可以学习一下。
至于线段树则十分巧妙了
code:
只可意会,不可言传
(其实是懒。。)
#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 1000000000
#define ll long long
using namespace std;
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;
}
int n,m;
struct data{
int l,r,ans;
double val,lx,mx;
}t[400005];
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;int mid=(l+r)>>1;
if(l==r)return;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
int cal(int k,double val){
int l=t[k].l,r=t[k].r;
if(l==r)return t[k].val>val;
if(t[k<<1].val<=val)return cal(k<<1|1,val);
return t[k].ans-t[k<<1].ans+cal(k<<1,val);
}
void modify(int k,int pos,double val){
int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
if(l==r){
t[k].ans=1;
t[k].val=val;
return;
}
if(pos<=mid)modify(k<<1,pos,val);
else modify(k<<1|1,pos,val);
t[k].val=max(t[k<<1].val,t[k<<1|1].val);
t[k].ans=t[k<<1].ans+cal(k<<1|1,t[k<<1].val);
}
int main(){
n=read();m=read();
build(1,1,n);
while(m--){
int x=read(),y=read();
modify(1,x,(double)y/x);
printf("%d\n",t[1].ans);
}
return 0;
}