bzoj 3307: 雨天的尾巴

来源:互联网 发布:excel 数据透视表 编辑:程序博客网 时间:2024/04/29 10:44
卡常数+卡内存,如果离散化了应该能好很多,但是我犯逗没有这么做
首先如果是序列上在一段内加入一个数,那么就是在位置l +1,在位置r -1,然后用权值线段树维护最大值就行。
那放在树上呢?
dfs+线段树合并,这个做法好像可以解决很多在序列上按照奇奇怪怪方式扫描并维护奇奇怪怪的东西,然后搬到树上的问题。如果不是用线段树的维护,也可以启发式合并这么搞。
在x,y打上+1,lca(x,y) fa[lca(x,y)]打上-1,
然后访问所有儿子,得到儿子的权值线段树,分别与x的权值线段树合并。
线段树合并是n log n的复杂度证明:
开始总共有nlogn个节点,每次合并的复杂度是O(共同有的点的个数),每次访问到一对点,一定会删除其中一个,最多删除nlogn个点,所以复杂度nlogn
卡内存小技巧: 建树的时候只插入xy的,然后合并完当前节点再删除c,这样保证那条路径上有点,所以开2*n*log(1e9)内存就行。
但明明离散化一下就结束了呀。。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
#define N 100010
#define TR 6500100
using namespace std;
struct yts { int x,t,ne;} e[2*N];
int v[N],dep[N],fa[N][20],root[N],ans[N];
int ch[TR][2],mx[TR],ID[TR];
vector<int> vec[N];
int num=0,cnt=0,n;
void put(int x,int y)
{
num++; e[num].x=x; e[num].t=y;
e[num].ne=v[x]; v[x]=num;
}
void insert(int &i,int l,int r,int x,int d)
{
if (!i) i=++cnt;
if (l==r) { mx[i]+=d; ID[i]=l; return;}
int mid=(l+r)>>1;
if (x<=mid) insert(ch[i][0],l,mid,x,d);
else insert(ch[i][1],mid+1,r,x,d);
if (!ch[i][1]||mx[ch[i][0]]>=mx[ch[i][1]]) { mx[i]=mx[ch[i][0]]; ID[i]=ID[ch[i][0]];}
else { mx[i]=mx[ch[i][1]]; ID[i]=ID[ch[i][1]];}
}
int merge(int x,int y,int l,int r)
{
if (!x) return y;
if (!y) return x;
if (l==r) { mx[x]+=mx[y]; return x;}
int mid=(l+r)>>1;
ch[x][0]=merge(ch[x][0],ch[y][0],l,mid); ch[x][1]=merge(ch[x][1],ch[y][1],mid+1,r);
if (!ch[x][1]||mx[ch[x][0]]>=mx[ch[x][1]]) { mx[x]=mx[ch[x][0]]; ID[x]=ID[ch[x][0]];}
else { mx[x]=mx[ch[x][1]]; ID[x]=ID[ch[x][1]];}
return x;
}
void dfs1(int x)
{
for (int i=v[x];i;i=e[i].ne)
{
int y=e[i].t;
if (y!=fa[x][0])
{
dep[y]=dep[x]+1; fa[y][0]=x;
dfs1(y);
}
}
}
void dfs2(int x)
{
for (int i=v[x];i;i=e[i].ne)
{
int y=e[i].t;
if (y!=fa[x][0])
{
dfs2(y);
root[x]=merge(root[x],root[y],0,1e9);
}
}
for (int i=0;i<vec[x].size();i++) insert(root[x],0,1e9,vec[x][i],-1);
if (mx[root[x]]) ans[x]=ID[root[x]];
}
void build_lca()
{
for (int j=1;j<=18;j++)
for (int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int x,int y)
{
if (dep[x]<dep[y]) { int c=x; x=y; y=c;}
int t=dep[x]-dep[y];
for (int i=18;i>=0;i--)
if (t&(1<<i)) x=fa[x][i];
if (x==y) return x;
for (int i=18;i>=0;i--)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main()
{
//printf("%d\n",(sizeof(ch)*2+sizeof(v)*30)/1024/1024);
int m;
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
put(x,y); put(y,x);
}
dep[1]=1; dfs1(1); build_lca();
for (int i=1;i<=m;i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
int z=lca(x,y);
insert(root[x],0,1e9,c,1); insert(root[y],0,1e9,c,1);
vec[z].push_back(c);
if (fa[z][0]) vec[fa[z][0]].push_back(c);
}
dfs2(1);
for (int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}

0 0
原创粉丝点击