【题目分析】

问题放到了树上,直接链剖+线段树搞一搞。

调了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 ——树链剖分 线段树的更多相关文章

  1. GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树

    GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...

  2. 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 ...

  3. SPOJ QTREE Query on a tree ——树链剖分 线段树

    [题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...

  4. SPOJ GSS7 - Can you answer these queries VII

    板的不能再板,链剖+线段树或者是LCT随便维护. 感觉唯一要注意的是跳链的时候要对$x$向上跳和$y$向上跳的情况分开讨论,而不能直接$swap$,因为只有两段接触的端点才能相互合并,而且每一次向上跳 ...

  5. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

  6. SPOJ 375 (树链剖分+线段树)

    题意:一棵包含N 个结点的树,每条边都有一个权值,要求模拟两种操作:(1)改变某条边的权值,(2)询问U,V 之间的路径中权值最大的边. 思路:最近比赛总是看到有树链剖分的题目,就看了论文,做了这题, ...

  7. spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)

    传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...

  8. 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, ...

  9. SP6779 GSS7 - Can you answer these queries VII

    纯数据结构题,没有思维难度.直接用线段树求最大子段和的方法完成树上路径的合并.注意链上合并顺序要符合序列的前后顺序. #include <cstdio> #include <cstr ...

随机推荐

  1. 将生成的Excel表发送到邮箱

    本文接上一篇,将得到的Excel表发送到邮箱.. 在上一篇中,本人使用的是直接从数据库中获取数据,然后包装成Excel表.现在将该Excel表发送到目的邮箱,如果需要跟上篇一样,定时每天某时刻发送,就 ...

  2. 模拟一次CSRF(跨站请求伪造)例子,适合新手

    GET请求伪造 有一个论坛网站,网站有一个可以关注用户的接口,但是必须登录的用户才可以关注其他用户. 这个网站的网站是www.a.com 有一天有一个程序员想提高自己的知名度,决定利用CSRF让大家关 ...

  3. selenium-Python之鼠标事件

    通过click()来模拟鼠标的单击操作,鼠标还具有鼠标右击,双击,悬停甚至鼠标拖动等功能.在webdriver中,将这些鼠标操作方法封装在ActionChains类提供. ActionChains类提 ...

  4. Web项目之Django实战问题剖析

    基于AdminLTE-master模板的后台管理系统 左侧菜单栏的二级标签设计 面包屑 Django文件上传 后台管理系统CRM项目设计流程分析

  5. 四、绘图可视化之Seaborn

    Seaborn-Powerful Matplotlib Extension seaborn实现直方图和密度图 import numpy as np import pandas as pd import ...

  6. 使用jQuery 发送Ajax

    jQuery AJAX 方法 AJAX 是一种与服务器交换数据的技术,可以在不重新载入整个页面的情况下更新网页的一部分. 下面的表格列出了所有的 jQuery AJAX 方法: 构建页面:jqlogi ...

  7. C++的反射

    写得挺不错,支持转帖下 C++语言本身是不支持反射的,但实际应用中总是会有将对象序列化的需求,总不可能C++不支持,我们就不用C++了,既然发明C++的大师们没有考虑这个,那我们只有自己动手了,毛主席 ...

  8. js常用技巧汇总

    将彻底屏蔽鼠标右键 oncontextmenu="window.event.returnvalue=false" <table border oncontextmenu=re ...

  9. 【分块】[HNOI2010]弹飞绵羊&分块大法祭

    分块(似乎还有一种动态树(LCT)做法) 第一次学习分块,似乎有点小激动 这是黄学长的分块入门博客「分块」数列分块入门1 – 9 by hzwer 题目描述 某天,Lostmonkey发明了一种超级弹 ...

  10. 嵌入式之:Linux下文件编译过程

    本文主要三个部分:1.GNU GCC简介 2.C/C++交叉编译器arm-elf-gcc 3.make文件,用于工程管理 部分一:GNU GCC简介: 该编译器基本功能: (1)输出预处理后的文件(展 ...