SPOJ GSS7 Can you answer these queries VII ——树链剖分 线段树
【题目分析】
问题放到了树上,直接链剖+线段树搞一搞。
调了300行+。
(还是码力不够)
【代码】
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib> #include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm> using namespace std; #define maxn 1000005
#define eps 1e-8
#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i) void Finout()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("wa.txt","w",stdout);
#endif
} int Getint()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
} struct Node{
int lx,rx,mx,sum,lazy;
Node operator + (Node x)
{
Node ret;
ret.lx=max(lx,sum+x.lx);
ret.rx=max(x.sum+rx,x.rx);
ret.sum=sum+x.sum;
ret.mx=max(max(mx,x.mx),max(rx+x.lx,max(ret.lx,ret.rx)));
ret.lazy=-inf;
return ret;
}
void print()
{
printf("lx %d rx %d sum %d mx %d lazy %d\n",lx,rx,sum,mx,lazy);
}
void init(){lx=rx=mx=sum=0;lazy=-inf;}
}t[maxn]; int n,a[maxn],b[maxn],q,L,R,tot,x,y,c;
int h[maxn],to[maxn],ne[maxn],en=0;
int fa[maxn],top[maxn],dep[maxn],siz[maxn],pos[maxn],son[maxn]; void add(int a,int b)
{
to[en]=b; ne[en]=h[a]; h[a]=en++;
to[en]=a; ne[en]=h[b]; h[b]=en++;
} void build(int o,int l,int r)
{
if (l==r)
{
t[o].lx=t[o].rx=t[o].mx=t[o].sum=a[l];
t[o].lazy=-inf;
return ;
}
int mid=l+r>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
t[o]=t[o<<1]+t[o<<1|1];
t[o].lazy=-inf;
} void dfs1(int o)
{
siz[o]=1;
for (int i=h[o];i>=0;i=ne[i])
{
if (to[i]!=fa[o])
{
fa[to[i]]=o;
dep[to[i]]=dep[o]+1;
dfs1(to[i]);
siz[o]+=siz[to[i]];
if (siz[to[i]]>siz[son[o]]) son[o]=to[i];
}
}
} void dfs2(int o,int tp)
{
top[o]=tp;
pos[o]=++tot;
a[tot]=b[o];
if (!son[o]) return ;
dfs2(son[o],tp);
for (int i=h[o];i>=0;i=ne[i])
if ((to[i]!=fa[o])&&(to[i]!=son[o]))
dfs2(to[i],to[i]);
return ;
} Node q1[maxn],q2[maxn]; void cov(int o,int c,int l,int r)
{
// printf("Node %d %d %d %d\n",o,c,l,r);
t[o].lx=c<0?c:(r-l+1)*c; //printf("%d %d\n",c,(l-r+1)*c);
t[o].rx=c<0?c:(r-l+1)*c;
t[o].sum=(r-l+1)*c;
t[o].mx=c<0?c:(r-l+1)*c;
// printf("lx:%d rx:%d sum:%d mx:%d\n",t[o].lx,t[o].rx,t[o].sum,t[o].mx);
} void pushdown(int o,int l,int r)
{
int mid=l+r>>1;
if (t[o].lazy!=-inf)
{
// printf("pushdown %d\n",o);
// printf("in %d\n",t[o].lazy);
t[o<<1].lazy=t[o<<1|1].lazy=t[o].lazy;
cov(o<<1,t[o].lazy,l,mid);
cov(o<<1|1,t[o].lazy,mid+1,r);
}
t[o].lazy=-inf;
} Node Query(int o,int l,int r)
{
// printf("q down\n");
pushdown(o,l,r);
// printf("Query %d %d\n",l,r);
if (L<=l&&r<=R) return t[o];
int mid=l+r>>1;
if (L>mid) return Query(o<<1|1,mid+1,r);
else if (R<=mid) return Query(o<<1,l,mid);
else return Query(o<<1,l,mid)+Query(o<<1|1,mid+1,r);
} void query()
{
x=Getint(); y=Getint();
// printf("Query %d to %d\n",x,y);
int p1=0,p2=0;
while (top[x]!=top[y])
{
if (dep[top[x]]>dep[top[y]])
{
L=pos[top[x]]; R=pos[x];
q1[++p1]=Query(1,1,n);
// printf("Query %d %d\n",L,R);
// printf("at q1\n"); q1[p1].print();
// printf("x: %d to %d\n",x,fa[top[x]]);
x=fa[top[x]];
}
else
{
L=pos[top[y]]; R=pos[y];
// printf("%d %d\n",L,R);
q2[++p2]=Query(1,1,n);
// printf("Query %d %d\n",L,R);
// printf("at q2\n"); q2[p2].print();
// printf("y: %d to %d\n",y,fa[top[y]]);
y=fa[top[y]];
}
}
if (dep[x]>=dep[y])
{
L=pos[y]; R=pos[x];
// printf("%d %d\n",L,R);
q1[++p1]=Query(1,1,n);
// printf("Query %d %d\n",L,R);
// printf("at q1\n"); q1[p1].print();
}
else
{
L=pos[x]; R=pos[y];
// printf("%d %d\n",L,R);
q2[++p2]=Query(1,1,n);
// printf("Query %d %d\n",L,R);
// printf("at q2\n"); q2[p2].print();
}
/* Node ret1,ret2,ret; ret1.init();ret2.init();ret.init();
printf("q1begin\n");
D(i,p1,1)
{
ret1.print();
ret1=ret1+q1[i];
q1[i].print();
ret1.print();
}
printf("q1 over\n");
ret1.print();
printf("q2 begin\n");
D(i,p2,1)
{
ret2.print();
ret2=ret2+q2[i];
q2[i].print();
ret2.print();
}
printf("q2 over\n");
// ret1.init(); ret2.init();
ret1.print(); ret2.print();
swap(ret2.lx,ret2.rx);
ret=ret1+ret2;
*/
Node ret,ret1,ret2; ret.init(); ret1.init(); ret2.init();
if (!p1)
{
// printf("only p2\n");
ret=q2[1];
F(i,2,p2) ret=q2[i]+ret;
}
else if (!p2)
{
// printf("only p1\n");
ret=q1[1];
F(i,2,p1) ret=q1[i]+ret;
}
else
{
// printf("both p1 and p2\n");
ret1=q1[1];
F(i,2,p1) ret1=q1[i]+ret1;
ret2=q2[1];
F(i,2,p2) ret2=q2[i]+ret2;
swap(ret2.lx,ret2.rx);
ret=ret2+ret1;
}
printf("%d\n",max(ret.mx,0));
} void mod(int o,int l,int r)
{
// printf("mod %d %d %d\n",o,l,r);
pushdown(o,l,r);
int mid=l+r>>1;
if (L<=l&&r<=R)
{
// printf("tag on %d by %d %d to %d\n",o,c,l,r);
t[o].lazy=c;
cov(o,c,l,r);
return ;
}
if (L<=mid) mod(o<<1,l,mid);
if (R>mid) mod(o<<1|1,mid+1,r);
t[o]=t[o<<1]+t[o<<1|1];
} void Modify()
{
x=Getint(); y=Getint(); c=Getint();
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
L=pos[top[x]]; R=pos[x];
// printf("modify %d %d %d\n",L,R,c);
mod(1,1,n);
x=fa[top[x]];
}
if (dep[x]<dep[y]) swap(x,y);
L=pos[y]; R=pos[x];
// printf("modify %d %d %d\n",L,R,c);
mod(1,1,n);
} int main()
{
memset(h,-1,sizeof h);
Finout(); n=Getint();
F(i,1,n) b[i]=Getint();
F(i,1,n-1) add(Getint(),Getint());
dfs1(1); dep[0]=-1;
dfs2(1,1);
// F(i,1,n) printf("Node %d : fa %d pos %d dep %d\n",i,fa[i],pos[i],dep[i]);
build(1,1,n);
q=Getint();
F(i,1,q)
{
int opt=Getint();
switch(opt)
{
case 1: query(); break;
case 2: Modify(); break;
}
}
}
SPOJ GSS7 Can you answer these queries VII ——树链剖分 线段树的更多相关文章
- GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树
GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...
- SPOJ QTREE Query on a tree 树链剖分+线段树
题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...
- SPOJ QTREE Query on a tree ——树链剖分 线段树
[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...
- SPOJ GSS7 - Can you answer these queries VII
板的不能再板,链剖+线段树或者是LCT随便维护. 感觉唯一要注意的是跳链的时候要对$x$向上跳和$y$向上跳的情况分开讨论,而不能直接$swap$,因为只有两段接触的端点才能相互合并,而且每一次向上跳 ...
- QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树
Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...
- SPOJ 375 (树链剖分+线段树)
题意:一棵包含N 个结点的树,每条边都有一个权值,要求模拟两种操作:(1)改变某条边的权值,(2)询问U,V 之间的路径中权值最大的边. 思路:最近比赛总是看到有树链剖分的题目,就看了论文,做了这题, ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- SP6779 GSS7 - Can you answer these queries VII
纯数据结构题,没有思维难度.直接用线段树求最大子段和的方法完成树上路径的合并.注意链上合并顺序要符合序列的前后顺序. #include <cstdio> #include <cstr ...
随机推荐
- POJ 1739 Tony's Tour (插头DP,轮廓线DP)
题意:给一个n*m的矩阵,其中#是障碍格子,其他则是必走的格子,问从左下角的格子走到右下角的格子有多少种方式. 思路: 注意有可能答案是0,就是障碍格子阻挡住了去路. 插头DP有两种比较常见的表示连通 ...
- openstack No valid host was found. There are not enough hosts available.
root@dell-PowerEdge-T30:~# gedit /var/log/nova/nova-conductor.logroot@dell-PowerEdge-T30:~# gedit /v ...
- C++数据文件存储与加载(利用opencv)
首先请先确认已经安装好了opencv3及以上版本. #include <opencv2/opencv.hpp>#include <iostream>#include <s ...
- shell 复合条件测试 if [ $1 == "1" -o $1 == "0" ] ------==和-eq怎么用
想要实现: ”,或者$1等于“” ];then 输出一些东西 ”,或者$1等于“” ];then 输出一些东西 fi 这里比较难操作的是等于和或者: 等于: -eq 或者 == 或者: -o 见: ...
- CAD交互绘制矩形批注(网页版)
js中实现代码说明: 动态拖放时的绘制事件: function DynWorldDrawComment2( pCustomEntity,pWorldDraw, curPt) { // 得到绘制参数. ...
- Java产生GUID
/** * 产生GUID */public static final String generateGUID(){ UUID uuid = UUID.randomUUID(); return uuid ...
- LeetCode 买卖股票的最佳时机 II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多笔交易(你必须在再次 ...
- ZJOI2018游记Round2
Day0 趁着空档还溜回班上了一节物理课:瓢泼之中在9:00赶往余姚,车程3h+-- 中饭在一家饭馆,味道海星. 晚上和ykh,chj,xzt溜去吃一鸣和烧烤.一鸣不错,烧烤的话我因为口腔溃疡没怎么吃 ...
- nginx 无法加载css/js图片等文件 404 not fund
刚配置Nginx反向代理,Nginx可能会出现无法加载css.js或者图片等文件,这里需要在配置文件*.conf里面加上如下配置项. location ~ .*\.(js|css|png|jpg)$ ...
- HUAWEI交换机配置telnet登录
Huawei交换机配置Telnet登录 一,交换机开启Telnet服务 <Huawei>system-view ...