• luogu P4756 Added Sequence(凸包+思维)


    一眼望去不会。
    考虑问题中的(f(i,j)=|sum_{p=i}^{j}​a_p​ |)的实际意义。
    其实就是前缀和相减的绝对值。
    (f(i,j)=| sum[j]-sum[i-1] |)
    (f(i,j)=max(sum[j]-sum[i-1],sum[i-1]-sum[j]))
    那加上x呢。
    (f(i,j)=max[(sum[j]+xj)-(sum[i-1]+x(i-1)),(sum[i-1]+x(i-1))-(sum[j]+xj)])
    (sum[i]+xi)联想到直线。
    我们把这些直线放到坐标系里。
    (这个图是从别人那里蒯过来的)

    这是把样例转为坐标系中直线的效果图。
    对于一个 (x) ,我们询问的实际上就是横坐标为x的两条直线纵坐标的差的最大值。
    所以我们用半平面交的方法维护出上下两个凸包。
    因为题目中的强制在线是假的(实际上处理出的(xin [-2n,2n]))。
    又因为凸包上的线段斜率是单调的,我们可以直接处理出所有 (x) 时的答案。
    然后这题就解决了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<map>
    using namespace std;
    const int N=201000;
    const double eps=1e-8;
    double sum[N];
    struct node{
    	double x,y;
    	node(double xx=0,double yy=0){
    		x=xx;y=yy;
    	}
    };
    int top1,top2;
    struct Line{
    	node u,v;
    	double w;
    }a[N],stack1[N],stack2[N];
    node operator +(node a,node b){
    	return node(a.x+b.x,a.y+b.y);
    }
    node operator -(node a,node b){
    	return node(a.x-b.x,a.y-b.y);
    }
    node operator *(node a,double b){
    	return node(a.x*b,a.y*b);
    }
    double chaji(node a,node b){
    	return a.x*b.y-a.y*b.x;
    }
    node jiao(Line a,Line b){
    	double A=chaji(b.u-a.u,b.v-a.u);
    	double B=chaji(b.v-a.v,b.u-a.v);
    	return a.u+(a.v-a.u)*(A/(A+B));
    }
    bool judge1(Line a,Line b,Line c){
    	node x=jiao(b,c);
    	if(chaji(x-a.u,a.v-a.u)+eps>=0)return true;
    	else return false;
    }
    bool judge2(Line a,Line b,Line c){
    	node x=jiao(b,c);
    	if(chaji(x-a.u,a.v-a.u)+eps<0)return true;
    	else return false;
    }
    int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return sum*f;
    }
    int n,m;
    double w(Line a,double x){
    //	cout<<a.w<<endl;
    	return a.u.y+a.w*(x-(-2.0*n));
    }
    map<int,double>ans;
    long long lastans;
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+read();
    	for(int i=1;i<=n;i++){
    		a[i].u=node(-2.0*n,sum[i]+i*-2.0*n);
    		a[i].v=node(2.0*n,sum[i]+i*2.0*n);
    		a[i].w=i;
    	}
    	a[0].u=node(-2.0*n,0);a[0].v=node(2.0*n,0);
    	a[0].w=0;
    	for(int i=0;i<=n;i++){
    		while(top1>1&&judge1(a[i],stack1[top1-1],stack1[top1]))top1--;
    		stack1[++top1]=a[i];
    	}
    	for(int i=n;i>=0;i--){
    		while(top2>1&&judge2(a[i],stack2[top2-1],stack2[top2]))top2--;
    		stack2[++top2]=a[i];
    	}
    	int now1=1;int now2=1;
    	for(int i=-2*n;i<=n*2;i++){
    		while(now1<top1&&w(stack1[now1+1],i)>=w(stack1[now1],i))now1++;
    		while(now2<top2&&w(stack2[now2+1],i)<=w(stack2[now2],i))now2++;
    		double A=w(stack1[now1],i);
    		double B=w(stack2[now2],i);
    		ans[i]=A-B;
    	}
    	lastans=0;
    	while(m--){
    		int x=read();
    		x=(x+lastans)%(4*n+1)-2*n;
    		lastans=ans[x];
    		printf("%.0lf
    ",ans[x]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    20款时尚的 WordPress 博客主题【免费下载】
    垂涎欲滴!30个美味的食品类移动应用程序【上篇】
    Skippr – 轻量、快速的 jQuery 幻灯片插件
    Boba.js – 用于 Google 统计分析 JavaScript 库
    长期这么做的后果就是人民劳苦而得不到该有的回报,怎么能不垮
    左值与右值的根本区别在于能否获取内存地址,而能否赋值不是区分的依据
    百度后端C++电话一面
    Web 开发和数据科学家仍是 Python 开发的两大主力
    Consul架构
    去除两端逗号-JS
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/10611159.html
Copyright © 2020-2023  润新知