2017.9.14 棘手的操作 思考记录
2017-09-14 10:46
134 查看
mdzz,手残没法治
一开始想按编号顺序用splay维护最值,但没法查找
然后想用线段树启发式合并,然而空间会爆
由于连接之后的连通块顺序没有关系,所以可以考虑并查集来表示区间,然后就可以用线段树维护了(坚决不写左偏树)
注意:
1、统计并查集一定找父节点,不要扫(因为集合和编号顺序没关系)
2、标记有时可以是负值,不要zz的写>0
3、开对空间
码:
#include<iostream>
#include<cstdio>
using namespace std;
#define zuo o<<1,l,mid
#define you o<<1|1,mid+1,r
#include<vector>
#define N 300005
vector<int>v1
;
int fu
,sz
,i,ans,v[N<<2],jbj[N<<2],va
,a,b,c,n,vv
,m,x,y,j,cnt,dui
;
char ch[9];
bool yw
;
int find(int o)
{
if(fu[o]!=o)fu[o]=find(fu[o]);
return fu[o];
}
struct wen
{
int op;
int x;
int y;
}w
;
void up(int o)
{
v[o]=max(v[o<<1],v[o<<1|1]);
}
void down(int o,int l,int r)
{
if(jbj[o]!=0)
{
int ll=o<<1;
int rr=o<<1|1;
v[ll]+=jbj[o];
v[rr]+=jbj[o];
jbj[ll]+=jbj[o];
jbj[rr]+=jbj[o];
jbj[o]=0;
}
}
void jian(int o,int l,int r)
{
if(l==r)
{
v[o]=va[l];
return;
}
int mid=(l+r)>>1;
jian(zuo);
jian(you);
up(o);
}
void gai(int o,int l,int r)
{
if(a<=l&&r<=b)
{
if(w[i].op>=1&&w[i].op<=3)
{v[o]+=c;
jbj[o]+=c;
}
if(w[i].op>=4&&w[i].op<=6)
ans=max(ans,v[o]);
return;
}
down(o,l,r);
int mid=(l+r)>>1;
if(a<=mid)gai(zuo);
if(b>mid)gai(you);
up(o);
}
int main()
{//freopen("pair.in","r",stdin);
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&vv[i]);
v1[i].push_back(i);
sz[i]=1;
fu[i]=i;
}
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%s",ch);
if(ch[0]=='U')
{
scanf("%d%d",&x,&y);
w[i].op=0;
w[i].x=x;
w[i].y=y;
int fx=find(x),fy=find(y);
if(fx==fy)continue;
if(sz[fx]<sz[fy])
{
fu[fx]=fy;
sz[fy]+=sz[fx];
for(j=0;j<v1[fx].size();j++)
v1[fy].push_back(v1[fx][j]);
}else
{
fu[fy]=fx;
sz[fx]+=sz[fy];
for(j=0;j<v1[fy].size();j++)
v1[fx].push_back(v1[fy][j]);
}
}
if(ch[0]=='A')
{
if(ch[1]=='1')
{ w[i].op=1;
scanf("%d%d",&w[i].x,&w[i].y);
}
if(ch[1]=='2')
{ w[i].op=2;
scanf("%d%d",&w[i].x,&w[i].y);
}
if(ch[1]=='3')
{ w[i].op=3;
scanf("%d",&w[i].x);
}
}
if(ch[0]=='F')
{
if(ch[1]=='1')
{ w[i].op=4;
scanf("%d",&w[i].x);
}
if(ch[1]=='2')
{ w[i].op=5;
scanf("%d",&w[i].x);
}
if(ch[1]=='3') w[i].op=6;
}
}
for(i=1;i<=n;i++)
{
int o=find(i);
if(yw[o])continue;
yw[o]=1;
// if(yw[i])continue;
for(j=0;j<v1[o].size();j++)
{
// cout<<v1[o][j]<<" ";
va[++cnt]=vv[v1[o][j]];
dui[v1[o][j]]=cnt;
}
}
for(i=1;i<=n;i++)sz[i]=1,fu[i]=i;
jian(1,1,n);
for(i=1;i<=m;i++)
{
if(w[i].op==0)
{
int fx=find(w[i].x),fy=find(w[i].y);
if(fx==fy)continue;
if(sz[fx]<sz[fy])
{
fu[fx]=fy;
sz[fy]+=sz[fx];
}else
{
fu[fy]=fx;
sz[fx]+=sz[fy];
}
}
if(w[i].op==1)
{
a=b=dui[w[i].x];
c=w[i].y;
gai(1,1,n);
}
if(w[i].op==2)
{
int fx=find(w[i].x);
a=dui[fx];
b=dui[fx]+sz[fx]-1;
c=w[i].y;
gai(1,1,n);
}
if(w[i].op==3)
{
a=1;
b=n;
c=w[i].x;
gai(1,1,n);
}
if(w[i].op==4)
{
a=b=dui[w[i].x];
ans=-1000000009;
gai(1,1,n);
printf("%d\n",ans);
}
if(w[i].op==5)
{
int fx=find(w[i].x);
a=dui[fx];
b=dui[fx]+sz[fx]-1;
ans=-1000000009;
gai(1,1,n);
printf("%d\n",ans);
}
if(w[i].op==6)
{
a=1;
b=n;
ans=-1000000009;
gai(1,1,n);
printf("%d\n",ans);
}
}
}
一开始想按编号顺序用splay维护最值,但没法查找
然后想用线段树启发式合并,然而空间会爆
由于连接之后的连通块顺序没有关系,所以可以考虑并查集来表示区间,然后就可以用线段树维护了(坚决不写左偏树)
注意:
1、统计并查集一定找父节点,不要扫(因为集合和编号顺序没关系)
2、标记有时可以是负值,不要zz的写>0
3、开对空间
码:
#include<iostream>
#include<cstdio>
using namespace std;
#define zuo o<<1,l,mid
#define you o<<1|1,mid+1,r
#include<vector>
#define N 300005
vector<int>v1
;
int fu
,sz
,i,ans,v[N<<2],jbj[N<<2],va
,a,b,c,n,vv
,m,x,y,j,cnt,dui
;
char ch[9];
bool yw
;
int find(int o)
{
if(fu[o]!=o)fu[o]=find(fu[o]);
return fu[o];
}
struct wen
{
int op;
int x;
int y;
}w
;
void up(int o)
{
v[o]=max(v[o<<1],v[o<<1|1]);
}
void down(int o,int l,int r)
{
if(jbj[o]!=0)
{
int ll=o<<1;
int rr=o<<1|1;
v[ll]+=jbj[o];
v[rr]+=jbj[o];
jbj[ll]+=jbj[o];
jbj[rr]+=jbj[o];
jbj[o]=0;
}
}
void jian(int o,int l,int r)
{
if(l==r)
{
v[o]=va[l];
return;
}
int mid=(l+r)>>1;
jian(zuo);
jian(you);
up(o);
}
void gai(int o,int l,int r)
{
if(a<=l&&r<=b)
{
if(w[i].op>=1&&w[i].op<=3)
{v[o]+=c;
jbj[o]+=c;
}
if(w[i].op>=4&&w[i].op<=6)
ans=max(ans,v[o]);
return;
}
down(o,l,r);
int mid=(l+r)>>1;
if(a<=mid)gai(zuo);
if(b>mid)gai(you);
up(o);
}
int main()
{//freopen("pair.in","r",stdin);
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&vv[i]);
v1[i].push_back(i);
sz[i]=1;
fu[i]=i;
}
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%s",ch);
if(ch[0]=='U')
{
scanf("%d%d",&x,&y);
w[i].op=0;
w[i].x=x;
w[i].y=y;
int fx=find(x),fy=find(y);
if(fx==fy)continue;
if(sz[fx]<sz[fy])
{
fu[fx]=fy;
sz[fy]+=sz[fx];
for(j=0;j<v1[fx].size();j++)
v1[fy].push_back(v1[fx][j]);
}else
{
fu[fy]=fx;
sz[fx]+=sz[fy];
for(j=0;j<v1[fy].size();j++)
v1[fx].push_back(v1[fy][j]);
}
}
if(ch[0]=='A')
{
if(ch[1]=='1')
{ w[i].op=1;
scanf("%d%d",&w[i].x,&w[i].y);
}
if(ch[1]=='2')
{ w[i].op=2;
scanf("%d%d",&w[i].x,&w[i].y);
}
if(ch[1]=='3')
{ w[i].op=3;
scanf("%d",&w[i].x);
}
}
if(ch[0]=='F')
{
if(ch[1]=='1')
{ w[i].op=4;
scanf("%d",&w[i].x);
}
if(ch[1]=='2')
{ w[i].op=5;
scanf("%d",&w[i].x);
}
if(ch[1]=='3') w[i].op=6;
}
}
for(i=1;i<=n;i++)
{
int o=find(i);
if(yw[o])continue;
yw[o]=1;
// if(yw[i])continue;
for(j=0;j<v1[o].size();j++)
{
// cout<<v1[o][j]<<" ";
va[++cnt]=vv[v1[o][j]];
dui[v1[o][j]]=cnt;
}
}
for(i=1;i<=n;i++)sz[i]=1,fu[i]=i;
jian(1,1,n);
for(i=1;i<=m;i++)
{
if(w[i].op==0)
{
int fx=find(w[i].x),fy=find(w[i].y);
if(fx==fy)continue;
if(sz[fx]<sz[fy])
{
fu[fx]=fy;
sz[fy]+=sz[fx];
}else
{
fu[fy]=fx;
sz[fx]+=sz[fy];
}
}
if(w[i].op==1)
{
a=b=dui[w[i].x];
c=w[i].y;
gai(1,1,n);
}
if(w[i].op==2)
{
int fx=find(w[i].x);
a=dui[fx];
b=dui[fx]+sz[fx]-1;
c=w[i].y;
gai(1,1,n);
}
if(w[i].op==3)
{
a=1;
b=n;
c=w[i].x;
gai(1,1,n);
}
if(w[i].op==4)
{
a=b=dui[w[i].x];
ans=-1000000009;
gai(1,1,n);
printf("%d\n",ans);
}
if(w[i].op==5)
{
int fx=find(w[i].x);
a=dui[fx];
b=dui[fx]+sz[fx]-1;
ans=-1000000009;
gai(1,1,n);
printf("%d\n",ans);
}
if(w[i].op==6)
{
a=1;
b=n;
ans=-1000000009;
gai(1,1,n);
printf("%d\n",ans);
}
}
}
相关文章推荐
- 安卓跳转登录后如何记录之前的操作的问题思考
- 2017.6.27 树上操作 思考记录
- 2017.9.10 序列操作 思考记录
- 2017.9.14 dispatching 思考记录
- 2017.9.14 仪仗队 思考记录
- 2017.9.21 所驼门王的宝藏 思考记录
- Fzu 2082 过路费【树链剖分--边操作】模板记录
- RFID射频卡超市购物结算系统问题记录--写入卡片时,后台php无法操作数据库
- 对Dictionary操作 查找项和排序 [代码记录]
- Linux下对文件进行加密备份的操作记录
- vim 基础操作记录
- Linux 入门记录:三、Linux 文件基本操作管理
- 记录两个用pika和kombu实现的rabbitmq队列操作
- 【BZOJ2333】棘手的操作(左偏树,STL)
- linux操作记录
- 【转】Android使用SQLiteDatabase操作SQLite数据库【学习记录】
- Yii: 如何在CGridView组件中根据不同的记录行数据显示不同的操作
- 以求知心记录,以勤奋心思考,以坦诚心求教,以平常心成长,欢迎大家来指点我成长~
- 最近重新在Hadoop集群上安装apache-hive操作记录
- PowerDesigner15 操作记录