zoukankan      html  css  js  c++  java
  • 简单的数列题

    给定两个长度为 (n) 的数列 (a)(b),有 (m) 个操作,操作分为三类:

    • (1) (l) (r) (w) :将数列 (a) 中区间 ([l,r]) 内所有数加上 (w) ;

    • (2) (x) (y) :交换 (b_x)(b_y) ;

    • (3) (l) (r) : 求 (displaystyle max_{i=l}^r {a_icdot b_i}) .

    (1le n,mle 10^5, 0le a_ile 10^7, 0le b_ile 10^5, 0le w_ile 100) .


    考虑分块。每一块就直接维护 (max {a_icdot b_i}) .

    然后我们看操作。第二个操作十分简单,直接交换后暴力重构即可。第一个操作区间修改,两边的块也可以直接修改。关键在于中间的块。

    我们要求的元素的权值 (w_i=cntcdot b_i+c_i). ( (cnt) 为整块累加的值, (c_i=a_icdot b_i))

    我们发现这其实是一个一次函数。我们对于每个 (cnt) 要找到最大的 (w_i) .

    我们考虑对上面的式子变形,得到: (c_i=-cntcdot b_i+w_i).

    我们要求的 (w_i) 即为斜率为 (-cnt) 的直线经过所有 ((b_i,c_i)) ,与y轴的截距。显然最大截距的直线一定是凸壳的一条切线。同时我们发现随着 (cnt) 的增大,最大值的点的位置单调向右移动。

    这样我们对于每一块按 (b) 值排序,然后维护一个上凸壳。每次整块增加时直接打标记,然后向右移动最大值位置。

    单次修改复杂度为 $ displaystylefrac{n}{S}+Slog n$ , 取块大小 (S)(displaystyle sqrt{frac{n}{log n}}) 复杂度最优为 (O(sqrt{nlog n}))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define gc()(iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
    namespace io {
    	const int SIZE=(1<<21)+1;
    	char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55]; int qr;
    	inline void flush(){
    		fwrite(obuf,1,oS-obuf,stdout);
    		oS=obuf;
    	}
    	inline void putc(char x){
    		*oS++ = x;
    		if(oS==oT) flush();
    	}
    	template <class I>
    	inline void gi (I &x){
    		for(c=gc();c<'0'||c>'9';c=gc());
    		for(x=0;c<='9'&&c>='0';c=gc()) x=(x<<1)+(x<<3)+(c&15);
    	}
    	template <class I>
    	inline void print(I x){
    		if (!x) putc('0'); if(x < 0) putc('-'),x=-x;
    		while(x) qu[++qr]=x%10+'0',x/=10;
    		while(qr) putc(qu[qr--]);
    		putc('
    ');
    	}
    	struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
    }
    using io::gi;
    using io::print;
    const int N=100005,qN=1300;
    struct node
    {
    	ll a;
    	int b,id;
    	bool operator < (node x) const {
    		return b==x.b ? a<x.a : b<x.b;
    	}
    } g[N];
    int n,m,bel[N],k,s[qN][qN],tp[N],pos[N],br[N],p[N],b[N];
    ll add[N];
    #define top s[x][tp[x]]
    #define dtp s[x][tp[x]-1]
    #define Max(x) s[x][pos[x]]
    #define ri register int
    void build(int x)
    {
    	for(ri i=br[x-1]+1;i<=br[x];++i) g[i].a+=add[x];
    	add[x]=pos[x]=tp[x]=0;
    	sort(g+br[x-1]+1,g+br[x]+1);
    	for(ri i=br[x-1]+1;i<=br[x];++i)
    	{
    		p[g[i].id]=i;
    		while(tp[x]>1&&(g[i].a*g[i].b-g[top].a*g[top].b)*(g[top].b-g[dtp].b)
    					>=(g[top].a*g[top].b-g[dtp].a*g[dtp].b)*(g[i].b-g[top].b))--tp[x];
    		s[x][++tp[x]]=i;
    	}
    	for(pos[x]=1;pos[x]<tp[x]&&g[s[x][pos[x]+1]].a*g[s[x][pos[x]+1]].b
    		>=g[s[x][pos[x]]].a*g[s[x][pos[x]]].b;pos[x]++);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("easyseq.in","r",stdin);
    	freopen("easyseq.out","w",stdout);
    #endif
    	gi(n),gi(m);
    	int lg=0;for(;1<<lg+1<=n;++lg);
    	k=sqrt(n/lg);
    	for(ri i=1;i<=n;++i) bel[i]=(i-1)/k+1,gi(g[i].a);
    	for(ri i=1;i<=n;++i) gi(g[i].b),g[i].id=i;
    	for(ri i=1;i<=bel[n];++i) br[i]=min(n,i*k),build(i);
    	while(m--)
    	{
    		ri op,l,r; gi(op),gi(l),gi(r);
    		if(op==1)
    		{
    			ri x,y; gi(x);
    			for(;bel[l]==bel[l-1]&&l<=r;++l) g[p[l]].a+=x;
    			build(bel[l-1]);
    			if(l>r) continue;
    			for(y=bel[l];br[y]+1<=r;++y)
    			{
    				add[y]+=x;
    				for(;pos[y]<tp[y]&&(g[s[y][pos[y]+1]].a+add[y])*g[s[y][pos[y]+1]].b>=
    		   			(g[s[y][pos[y]]].a+add[y])*g[s[y][pos[y]]].b;pos[y]++);
    			}
    			for(l=(y-1)*k+1;l<=r;++l) g[p[l]].a+=x;
    			build(bel[r]);
    		}
    		if(op==2)
    		{
    			g[p[l]].b^=g[p[r]].b^=g[p[l]].b^=g[p[r]].b;
    			build(bel[l]),build(bel[r]);
    		}
    		if(op==3)
    		{
    			ll ans=0; ri y;
    			for(;bel[l]==bel[l-1]&&l<=r;++l)
    				ans=max(ans,(g[p[l]].a+add[bel[l]])*g[p[l]].b);
    			if(l>r) {
    				print(ans); continue;
    			}
    			for(y=bel[l];br[y]+1<=r;++y)
    				ans=max(ans,(g[Max(y)].a+add[y])*g[Max(y)].b);
    			for(l=(y-1)*k+1;l<=r;++l)
    				ans=max(ans,(g[p[l]].a+add[bel[l]])*g[p[l]].b);
    			print(ans); 
    		}
    	}
    }
    
  • 相关阅读:
    有限状态机(FSM)的简单理解和Python实现
    【Papers】Lane-Detection 近期车道线检测论文阅读总结
    刷LeetCode的简易姿势
    数码时代的效率生活
    轻量化模型训练加速的思考(Pytorch实现)
    编程之美!从线程池状态管理来看二进制操作之美
    没想到,Git居然有3种“后悔药”!
    交易系统高并发下的幂等性设计原则
    集群环境中使用Zookeeper实现分布式幂等控制
    Elasticsearch 入门到高手的成长阶梯-索引的基本操作(2)-索引的收缩和拆分
  • 原文地址:https://www.cnblogs.com/farway17/p/10425636.html
Copyright © 2011-2022 走看看