您的位置:首页 > 其它

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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: