当前位置: 首页 > wzjs >正文

网站蜘蛛爬行统计简述网络营销的含义

网站蜘蛛爬行统计,简述网络营销的含义,怎么查看一个网站是用什么程序做的,网站开发 技术指标洛谷P2042 [NOI2005] 维护数列 洛谷题目传送门 题目描述 请写一个程序,要求维护一个数列,支持以下 666 种操作: 编号名称格式说明1插入INSERT⁡positotc1c2⋯ctot\operatorname{INSERT}\ posi \ tot \ c_1 \ c_2 \cdots c_{tot}INSERT po…

洛谷P2042 [NOI2005] 维护数列

洛谷题目传送门

题目描述

请写一个程序,要求维护一个数列,支持以下 666 种操作:

编号名称格式说明
1插入INSERT⁡positotc1c2⋯ctot\operatorname{INSERT}\ posi \ tot \ c_1 \ c_2 \cdots c_{tot}INSERT posi tot c1 c2ctot在当前数列的第 posiposiposi 个数字后插入 tottottot 个数字:c1,c2⋯ctotc_1, c_2 \cdots c_{tot}c1,c2ctot;若在数列首插入,则 posiposiposi000
2删除DELETE⁡positot\operatorname{DELETE} \ posi \ totDELETE posi tot从当前数列的第 posiposiposi 个数字开始连续删除 tottottot 个数字
3修改MAKE-SAME⁡positotc\operatorname{MAKE-SAME} \ posi \ tot \ cMAKE-SAME posi tot c从当前数列的第 posiposiposi 个数字开始的连续 tottottot 个数字统一修改为 ccc
4翻转REVERSE⁡positot\operatorname{REVERSE} \ posi \ totREVERSE posi tot取出从当前数列的第 posiposiposi 个数字开始的 tottottot 个数字,翻转后放入原来的位置
5求和GET-SUM⁡positot\operatorname{GET-SUM} \ posi \ totGET-SUM posi tot计算从当前数列的第 posiposiposi 个数字开始的 tottottot 个数字的和并输出
6求最大子列和MAX-SUM⁡\operatorname{MAX-SUM}MAX-SUM求出当前数列中和最大的一段子列,并输出最大和

输入格式

第一行包含两个整数 NNNMMMNNN 表示初始时数列中数的个数,MMM 表示要进行的操作数目。

第二行包含 NNN 个数字,描述初始时的数列。以下 MMM 行,每行一条命令,格式参见问题描述中的表格。

输出格式

对于输入数据中的 GET-SUM⁡\operatorname{GET-SUM}GET-SUMMAX-SUM⁡\operatorname{MAX-SUM}MAX-SUM 操作,向输出文件依次打印结果,每个答案(数字)占一行。

输入输出样例 #1

输入 #1

9 8 
2 -6 3 5 1 -5 -3 6 3 
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

输出 #1

-1
10
1
10

说明/提示

数据规模与约定
  • 你可以认为在任何时刻,数列中至少有 111 个数。
  • 输入数据一定是正确的,即指定位置的数在数列中一定存在。
  • 对于 50%50\%50% 的数据,任何时刻数列中最多含有 3×1043 \times 10^43×104 个数。
  • 对于 100%100\%100% 的数据,任何时刻数列中最多含有 5×1055 \times 10^55×105 个数,任何时刻数列中任何一个数字均在 [−103,103][-10^3, 10^3][103,103] 内,1≤M≤2×1041 \le M \le 2 \times 10^41M2×104,插入的数字总数不超过 4×1064 \times 10^64×106

题面由 @syksykCCC 提供。

思路详解

确定算法

根据我们的目测,这显然是一个裸数据结构的题,由于他要区间翻转,我们很容易就想到了要使用平衡树,不会区间翻转的可以去看这道题。在这里我采用的是无旋平衡树(FHQ)。下面我将为你相信讲解这道题。

一切的根基

由于我采用的是指针,我们首先要定义好结构体,并做好安全访问的每一个元素的函数,具体如下:

struct lit{int val,sum,pri,siz;
//值,区间和,优先级,大小int pre,suf,sub;
//最大前缀,最大后缀,最大子序列int co,rev;
//染色,翻转的懒标记lit *l,*r;
//左右子节点lit(int v){//构造val=sum=sub=v;//由于要求必须有一个元素,所以sub=v(后面会解释pre与suf)pri=rand();siz=1;pre=suf=max(0,v);co=-0x3f3f3f3f;rev=0;l=r=nullptr;}
};
//............................
int getsum(lit *u){return u?u->sum:0;}//安全访问
int getsize(lit *u){return u?u->siz:0;}
int getsub(lit *u){return u?u->sub:-0x3f3f3f3f;}
int getpre(lit *u){return u?u->pre:0;}
int getsuf(lit *u){return u?u->suf:0;}

打标记,更新与下传

我们要进行两种标记:

  1. 区间染色:染色了再翻转就没意义了,我们可以进行一下优化,染色后sum,pre,sub,suf,valsum,pre,sub,suf,valsum,pre,sub,suf,val都要改变,与构造差不多。
  2. 区间翻转:翻转首先要交换左右子树,然后,pre,sufpre,sufpre,suf也要交换。
void mark_co(lit *&u,int v){//区间染色if(!u)return;u->co=v;//更新标记u->sum=u->siz*v;//更新区间和u->val=v;//更新单点的值u->pre=u->suf=max(u->sum,0);//更新pre,suf,同上u->sub=max(v,u->sum);//sub至少一个元素,所以要么只取一个,要么全部取u->rev=0;//不需要翻转了}void mark_rev(lit *&u){//区间翻转if(!u)return;u->rev^=1;//更新标记swap(u->l,u->r);//交换左右子树swap(u->pre,u->suf);//交换pre,suf}

标记下传很简单,依次下传2个标记即可。

void pushdown(lit *&u){if(!u)return ;if(u->co!=-0x3f3f3f3f){//下传染色标记mark_co(u->l,u->co);mark_co(u->r,u->co);u->co=-0x3f3f3f3f;}if(u->rev){//下传翻转标记mark_rev(u->l);mark_rev(u->r);u->rev=0;}}

下面,到了本题比较难的部分了,那就是更新。更新的其他的值都没什么好说的,但我们要思考如何更新pre,suf,subpre,suf,subpre,suf,sub。我会在下面代码中详细讲解:

void pushup(lit *&u){if(!u)return;u->siz=1+getsize(u->l)+getsize(u->r);u->sum=getsum(u->l)+u->val+getsum(u->r);u->pre=max(max(getpre(u->l),getsum(u->l)+u->val+getpre(u->r)),0);
//最大前缀可能包含当前节点,也可能不。
//不包括时为getpre(u->l),包括时为getsum(u->l)+u->val+getpre(u->r)。u->suf=max(max(getsuf(u->r),getsum(u->r)+u->val+getsuf(u->l)),0);//同上u->sub=max(getsuf(u->l)+getpre(u->r)+u->val,max(getsub(u->l),getsub(u->r)));
//同理sub也可以包括或不包括,不包括时为max(getsub(u->l),getsub(u->r)),包括时为getsuf(u->l)+getpre(u->r)+u->val
}

FHQ核心

FHQ核心只有2个函数,分别为splitsplitsplit(分裂)与mergemergemerge(合并)。

void split(lit *u,int k,lit *&x,lit *&y){//分类if(!u){x=y=nullptr;return;}pushdown(u);//记得下传!!!int ls=getsize(u->l);if(ls+1<=k){x=u;split(u->r,k-ls-1,x->r,y);pushup(x);}else {y=u;split(u->l,k,x,y->l);pushup(y);}
}
lit *merge(lit *x,lit *y){if(!x)return y;if(!y)return x;pushdown(x);pushdown(y);//记得下传!!!if(x->pri>y->pri){x->r=merge(x->r,y);pushup(x);return x;}else{y->l=merge(x,y->l);pushup(y);return y;}
}

快速建点与删除

为了更好的完成此题,我们还要完成两个操作:

  1. 由于他要直接插入一个区间,所以我们要想办法快速生成这个区间,再合并即可。考虑同线段树一样二分处理。这样对mergemergemerge的调用只有log(n)log(n)log(n)次。
  2. 为了释放空间,我们要将一个区间彻底删除。
lit *add(int l,int r){//二分建树if(l==r)return new lit(t[l]);//边界int mid=(l+r)/2;return merge(add(l,mid),add(mid+1,r));}void clear(lit *&u){//递归删除if(!u)return ;clear(u->l);clear(u->r);delete u;}

封装

封装好每一个操作,我们的这道题就差不多了。

void insert(int p,int n){//加入一个区间lit *x,*y;split(root,p,x,y);root=merge(merge(x,add(1,n)),y);
}
void remove(int le,int ri){//删除区间[le,ri]lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);if(mid)clear(mid);root=merge(l,r);
}
void change_color(int le,int ri,int v){//区间染色lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);mark_co(mid,v);root=merge(merge(l,mid),r);
}
void change_reverse(int le,int ri){//区间翻转lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);mark_rev(mid);root=merge(merge(l,mid),r);
}
int query_sum(int le,int ri){//求区间和lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);int res=getsum(mid);root=merge(l,merge(mid,r));return res;
}
int query_sub(){//求整个区间的最大子序列return getsub(root); 
}

code

完整代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=4e6+5,INF=-0x3f3f3f3f;
struct lit{int val,sum,pri,siz;
//值,区间和,优先级,大小int pre,suf,sub;
//最大前缀,最大后缀,最大子序列int co,rev;
//染色,翻转的懒标记lit *l,*r;
//左右子节点lit(int v){//构造val=sum=sub=v;//由于要求必须有一个元素,所以sub=v(后面会解释pre与suf)pri=rand();siz=1;pre=suf=max(0,v);co=-0x3f3f3f3f;rev=0;l=r=nullptr;}
};
int t[N],n,m;
class FHQ_Treap{
private:lit *root;int getsum(lit *u){return u?u->sum:0;}//安全访问int getsize(lit *u){return u?u->siz:0;}int getsub(lit *u){return u?u->sub:-0x3f3f3f3f;}int getpre(lit *u){return u?u->pre:0;}int getsuf(lit *u){return u?u->suf:0;}void mark_co(lit *&u,int v){//区间染色if(!u)return;u->co=v;//更新标记u->sum=u->siz*v;//更新区间和u->val=v;//更新单点的值u->pre=u->suf=max(u->sum,0);//更新pre,suf,同上u->sub=max(v,u->sum);//sub至少一个元素,所以要么只取一个,要么全部取u->rev=0;//不需要翻转了}void mark_rev(lit *&u){//区间翻转if(!u)return;u->rev^=1;//更新标记swap(u->l,u->r);//交换左右子树swap(u->pre,u->suf);//交换pre,suf}void pushdown(lit *&u){if(!u)return ;if(u->co!=-0x3f3f3f3f){//下传染色标记mark_co(u->l,u->co);mark_co(u->r,u->co);u->co=-0x3f3f3f3f;}if(u->rev){//下传翻转标记mark_rev(u->l);mark_rev(u->r);u->rev=0;}}void pushup(lit *&u){if(!u)return;u->siz=1+getsize(u->l)+getsize(u->r);u->sum=getsum(u->l)+u->val+getsum(u->r);u->pre=max(max(getpre(u->l),getsum(u->l)+u->val+getpre(u->r)),0);
//最大前缀可能包含当前节点,也可能不。
//不包括时为getpre(u->l),包括时为getsum(u->l)+u->val+getpre(u->r)。u->suf=max(max(getsuf(u->r),getsum(u->r)+u->val+getsuf(u->l)),0);//同上u->sub=max(getsuf(u->l)+getpre(u->r)+u->val,max(getsub(u->l),getsub(u->r)));
//同理sub也可以包括或不包括,不包括时为max(getsub(u->l),getsub(u->r)),包括时为getsuf(u->l)+getpre(u->r)+u->val}void split(lit *u,int k,lit *&x,lit *&y){//分类if(!u){x=y=nullptr;return;}pushdown(u);//记得下传!!!int ls=getsize(u->l);if(ls+1<=k){x=u;split(u->r,k-ls-1,x->r,y);pushup(x);}else {y=u;split(u->l,k,x,y->l);pushup(y);}}lit *merge(lit *x,lit *y){if(!x)return y;if(!y)return x;pushdown(x);pushdown(y);//记得下传!!!if(x->pri>y->pri){x->r=merge(x->r,y);pushup(x);return x;}else{y->l=merge(x,y->l);pushup(y);return y;}}lit *add(int l,int r){//二分建树if(l==r)return new lit(t[l]);//边界int mid=(l+r)/2;return merge(add(l,mid),add(mid+1,r));}void clear(lit *&u){//递归删除if(!u)return ;clear(u->l);clear(u->r);delete u;}
public:void insert(int p,int n){//加入一个区间lit *x,*y;split(root,p,x,y);root=merge(merge(x,add(1,n)),y);}void remove(int le,int ri){//删除区间[le,ri]lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);if(mid)clear(mid);root=merge(l,r);}void change_color(int le,int ri,int v){//区间染色lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);mark_co(mid,v);root=merge(merge(l,mid),r);}void change_reverse(int le,int ri){//区间翻转lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);mark_rev(mid);root=merge(merge(l,mid),r);}int query_sum(int le,int ri){//求区间和lit *l,*mid,*r;split(root,ri,mid,r);split(mid,le-1,l,mid);int res=getsum(mid);root=merge(l,merge(mid,r));return res;}int query_sub(){//求整个区间的最大子序列return getsub(root); }
}tr;
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m;for(int i=1;i<=n;i++)cin>>t[i];tr.insert(0,n);for(int i=1;i<=m;i++){string s;int x,y,z;cin>>s;if(s=="INSERT"){cin>>x>>y;for(int j=1;j<=y;j++)cin>>t[j];tr.insert(x,y);}else if(s=="DELETE"){cin>>x>>y;tr.remove(x,x+y-1);}else if(s=="MAKE-SAME"){cin>>x>>y>>z;tr.change_color(x,x+y-1,z);}else if(s=="REVERSE"){cin>>x>>y;tr.change_reverse(x,x+y-1);}else if(s=="GET-SUM"){cin>>x>>y;cout<<tr.query_sum(x,x+y-1)<<'\n';}else{cout<<tr.query_sub()<<'\n';}}return 0;
}
http://www.dtcms.com/wzjs/357756.html

相关文章:

  • 百度竞价排名广告定价鲜花seo标签优化
  • 龙华新区城市建设局网站揭阳新站seo方案
  • 广州购网站建设刷关键词排名系统
  • 南昌网站设计公司郑州网
  • 网站建设开发方式包括哪些搜关键词网站
  • 安阳360网站推广工具舆情分析
  • 服务器怎么发布网站网络营销课程设计
  • wordpress播放上传视频seo软件哪个好
  • 怎样快速仿做网站怎么做网站链接
  • 东莞高端做网站公司千万不要做手游推广员
  • 正规做网站公司学企业管理培训班
  • MIUI官方网站开发版百度关键词搜索指数
  • 自己如何做网站推广企业网站的网络营销功能
  • 网站内链建设锚文字建设网络营销渠道有哪几种
  • 校园淘宝店网站开发在线seo关键词排名优化
  • 系统的网站建设教程市场推广方案怎么做
  • 织梦网站seo信息发布网站有哪些
  • 网站建设公司怎样拓展网站业务网站seo推广多少钱
  • 网站网络推广如何制作一个网页链接
  • 如何建设类似大众点评网站学生网页设计模板
  • 免费空间测试网站营销网站的建造步骤
  • 洛阳做网站的公司seo做的比较好的公司
  • 广东网站建设费用如何打百度人工电话
  • 网站建设提成湖南优化公司
  • 玉林做网站优化推广seo搜索优化推广
  • 测网站打开的速度的网址如何在各大网站发布信息
  • 高校门户网站建设问题网站推广方式有哪些
  • 国家企业信用查询官网广州网站运营专业乐云seo
  • wordpress类开源网站定向推广
  • 龙岗附近做网站公司2024很有可能再次封城吗