zoukankan      html  css  js  c++  java
  • 「HNOI2019」序列

    传送门

    Luogu

    题解

    终于看保序回归了吗

    首先送了( ext{50pts}),直接用保序回归例题1的做法即可。

    仔细分析一下,这个(B)就是(frac{sum A}{sum W}),那么我们考虑分成若干段之后的答案是:

    [egin{align} sum{(A_i-B)}^2&=sum A_i^2 + sum B^2- 2sum A_iB \ &=sum A_i^2+sum wfrac{sum A^2}{sum w^2}-2 imesfrac{sum A}{sum w} \ &=sum A_i^2 -frac{sum A^2}{sum w} end{align} ]

    所以只需要维护(sum A,sum w),前面这个(A_i^2)可以直接维护。

    const int N=200010,Mod=998244353;
    int n,m,A[N];
    int qpow(int a,int b){int ret=1;while(b){if(b&1)ret=1ll*ret*a%Mod;b>>=1;a=1ll*a*a%Mod;}return ret;}
    struct node
    {
    	ll x,y;
    	bool operator<(const node &b)const{return 1ll*x*b.y<1ll*y*b.x;}
    	node operator+(const node &b)const{return (node){x+b.x,y+b.y};}
    	int calc(){return 1ll*(x%Mod)*(x%Mod)%Mod*qpow(y%Mod,Mod-2)%Mod;}
    }sta[N];
    int calc()
    {
    	int ans=0,top=0;
    	for(int i=1;i<=n;i++)ans=(ans+1ll*A[i]*A[i]%Mod)%Mod;
    	for(int i=1;i<=n;i++)
    	{
    		node ret=(node){A[i],1};
    		while(top&&ret<sta[top]){ret=ret+sta[top];top--;}
    		sta[++top]=ret;
    	}
    	for(int i=1;i<=top;i++)ans=(ans-sta[i].calc()+Mod)%Mod;
    	return ans;
    }
    

    考虑(100pts),我们现在需要改变一个数字的值,然后维护这个栈。

    不难想到可以选择左边的一个栈位置,右边的一个栈位置((L0,R0)),然后合并成一段。

    那么考虑这个((L0,R0))的需求是合并成一段后对于前后都合法,这一段刚好可以合并成一段。

    也就是说对于一个(R0)我们要求一个最大的(L0),同时要求最大的(R0)

    所以我们可以二分(R0),然后二分(L0)即可。

    代码

    /*====================
    author: fexuile
    mail: fexuile@qq.com
    QQ: 2165008534
    ====================*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<iostream>
    #include<set>
    #include<map>
    using namespace std;
    #define mp make_pair
    #define ll long long
    #define re register
    typedef pair<int,int> pii;
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    inline int gi()
    {
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int N=200010,Mod=998244353;
    int n,m,x[N];
    int qpow(int a,int b){int ret=1;while(b){if(b&1)ret=1ll*ret*a%Mod;b>>=1;a=1ll*a*a%Mod;}return ret;}
    struct node
    {
    	ll x,y;
    	bool operator<(const node &b)const{return 1ll*x*b.y<1ll*y*b.x;}
    	node operator+(const node &b)const{return (node){x+b.x,y+b.y};}
    	int calc(){return 1ll*(x%Mod)*(x%Mod)%Mod*qpow(y%Mod,Mod-2)%Mod;}
    }staA[N],staB[N];
    int sA[N],sB[N],topA,topB,A[N],B[N],ans[N],ql,qr;
    ll sum[N][2];
    vector<pii>vec[N];
    void getL(int delta,int R0)
    {
    	int l=0,r=topA;
    	while(l<r)
    	{
    		int mid=(l+r+1)>>1;
    		if(staA[mid]<((node){sum[R0-1][0]-sum[A[mid]][0]+delta,R0-A[mid]-1}))l=mid;
    		else r=mid-1;
    	}
    	ql=l;
    }
    void getR(int delta)
    {
    	int l=0,r=topB;
    	while(l<r)
    	{
    		int mid=(l+r+1)>>1;getL(delta,B[mid]);
    		if(((node){sum[B[mid]-1][0]-sum[A[ql]][0]+delta,B[mid]-A[ql]-1})<staB[mid])l=mid;
    		else r=mid-1;
    	}
    	qr=l;getL(delta,B[qr]);
    }
    int solve(int delta)
    {
    	getR(delta);
    //	printf("%d %d %d
    ",A[ql],B[qr],delta);
    	return ((ll)sA[ql]+sB[qr]+((node){sum[B[qr]-1][0]-sum[A[ql]][0]+delta,B[qr]-A[ql]-1}).calc())%Mod;
    }
    vector<int>del[N];
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("in.in","r",stdin);
    #endif
    	n=gi();m=gi();
    	for(int i=1;i<=n;i++)x[i]=gi(),sum[i][0]=sum[i-1][0]+x[i],sum[i][1]=(sum[i-1][1]+1ll*x[i]*x[i]%Mod)%Mod;
    	for(int i=1;i<=m;i++)
    	{
    		int p=gi();
    		vec[p].push_back(mp(gi()-x[p],i));
    	}
    	B[0]=n+1;
    	for(int i=n;i;i--)
    	{
    		node ret=(node){x[i],1};
    		while(topB&&staB[topB]<ret)
    		{
    			del[i].push_back(B[topB]);
    			ret=ret+staB[topB];topB--;
    		}
    		staB[++topB]=ret;sB[topB]=(sB[topB-1]+ret.calc())%Mod;B[topB]=i;
    	}
    	printf("%d
    ",(sum[n][1]-sB[topB]+Mod)%Mod);
    	for(int i=1;i<=n;i++)
    	{
    		topB--;
    		for(int j=del[i].size()-1;~j;j--)
    		{
    			B[++topB]=del[i][j];
    			staB[topB]=(node){sum[B[topB-1]-1][0]-sum[B[topB]-1][0],B[topB-1]-B[topB]};
    			sB[topB]=(sB[topB-1]+staB[topB].calc())%Mod;
    		}
    		
    		int res=(sum[n][1]-1ll*x[i]*x[i]%Mod+Mod)%Mod;
    		for(auto id:vec[i])
    			ans[id.second]=((res+1ll*(x[i]+id.first)*(x[i]+id.first)%Mod)%Mod-solve(id.first)+Mod)%Mod;
    		
    		node ret=(node){x[i],1};
    		while(topA&&ret<staA[topA]){ret=ret+staA[topA];topA--;}
    		staA[++topA]=ret;sA[topA]=(sA[topA-1]+ret.calc())%Mod;A[topA]=i;
    	}
    	for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    使用 yo 命令行向导给 SAP UI5 应用添加一个新的视图
    SAP Fiori Elements 应用的 manifest.json 文件运行时如何被解析的
    SAP UI5 标准应用的多语言支持
    微软 Excel 365 里如何设置下拉菜单和自动高亮成指定颜色
    SAP Fiori Elements 应用里的 Title 显示的内容是从哪里来的
    本地开发好的 SAP Fiori Elements 应用,如何部署到 ABAP 服务器上?
    如何在 Cypress 测试代码中屏蔽(Suppress)来自应用代码报出的错误消息
    教你一招:让集群慢节点无处可藏
    应用架构步入“无服务器”时代 Serverless技术迎来新发展
    MySQL数据库事务隔离性的实现
  • 原文地址:https://www.cnblogs.com/fexuile/p/13197218.html
Copyright © 2011-2022 走看看