4 条题解

  • 0
    @ 2025-10-29 9:52:52

    20分做法

    按照题意模拟即可

    50分做法

    如果 jjii 这一段所有点中,jjii 的斜率是最大的,就能互相看到。

    复杂度 O(qn2)\mathcal O(qn^2),但在洛谷上已经能过了。

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=2005;
    int n,q,a[N];
    inline double slope(int i,int j) {return (a[i]-a[j])*1.0/(i-j);}
    double mx[N];
    signed main() {
    	cin>>n;
    	for(int i=1; i<=n; ++i) cin>>a[i];
    	cin>>q;
    	while(q--) {
    		int x,y,ans=0;
    		cin>>x>>y;
    		a[x]+=y;
    		for(int i=1; i<=n; ++i) mx[i]=-1e18;
    		for(int i=2; i<=n; ++i) {
    			for(int j=1; j<i; ++j) {
    				double s=slope(i,j);
    				if(mx[j]<=s) ++ans,mx[j]=s;
    			}
    		}
    		cout<<ans<<"\n";
    	}
    	return 0;
    }
    

    满分做法

    每一个人往后看,能看到的人与他连线的斜率是单调不降的。对于每一个人开一个 STL-set 存他往后能看到的人。每一次对于 xx,直接重构 xx 的 set。对于 xx 前面的所有 ii 也要更新,要把 xx 挡住的删掉,还要看看新的 xx 能不能让 ii 看见。这些用斜率判断就行了。

    对于 i<x<ji<x<j,如果 slope(i,x)>slope(i,j)slope(i,x)>slope(i,j)jj 就被挡住了。

    然后删的时候如果 set 本来有 xx,先把 xx 删掉,最后再加进去,这个地方特判一下。如果 xx 的前驱没有挡住 xx 就行。

    总共只会删除 nqnq 个。均摊下来复杂度 O((n2+nq)logn)\mathcal O((n^2+nq)\log n)

    #include<bits/stdc++.h>
    #define int long long
    #define R(x) x=read()
    using namespace std;
    inline int read() {
    	int x=0,y=1;
    	char e=getchar();
    	while(e<'0'||e>'9') {
    		if(e=='-')y=-1;
    		e=getchar();
    	}
    	while(e>='0'&&e<='9') {
    		x=(x<<1)+(x<<3)+(e^'0');
    		e=getchar();
    	}
    	return x*y;
    }
    const int N=2005;
    int n,q,a[N],ans;
    set<int>s[N];
    inline double slope(int i,int j) {return (double)(a[i]-a[j])/(i-j);}
    signed main() {
    	R(n);
    	for(int i=1; i<=n; ++i)R(a[i]);
    	for(int i=1; i<=n; ++i) {
    		double mx=-1e18;
    		for(int j=i+1; j<=n; ++j) {
    			if(slope(i,j)>=mx) mx=slope(i,j),s[i].insert(j);
    		}
    	}
    	for(int i=1; i<=n; ++i) ans+=s[i].size();
    	R(q);
    	while(q--) {
    		int x,y;
    		R(x),R(y);
    		a[x]+=y,s[x].clear();
    		double mx=-1e18;
    		for(int j=x+1; j<=n; ++j) {
    			if(slope(x,j)>=mx) mx=slope(x,j),s[x].insert(j);
    		}
    		for(int i=1; i<x; ++i) {
    			if(s[i].empty()) {
    				s[i].insert(x);
    				continue;
    			}
    			bool fl=1;
    			auto it=s[i].lower_bound(x);
    			if(it!=s[i].begin()){
    				--it;
    				if(slope(x,i)<slope(*it,i)) fl=0;
    				++it;
    			}
    			auto l=it,r=it;
    			while(r!=s[i].end()&&(*r==x||slope(x,i)>slope(*r,i))) ++r;
    			if(l!=r) s[i].erase(l,r);
    			if(fl) s[i].insert(x);
    		}
    		ans=0;
    		for(int i=1; i<=n; ++i) ans+=s[i].size();
    		cout<<ans<<"\n";
    	}
    	return 0;
    }
    

    信息

    ID
    524
    时间
    3000ms
    内存
    512MiB
    难度
    8
    标签
    (无)
    递交数
    16
    已通过
    6
    上传者