题目链接:

闲扯:

终于在集训中敲出正解(虽然与正解不完全相同),开心QAQ

首先比较巧,这题是\(Ebola\)出的一场模拟赛的一道题的树上强化版,当时还口胡出了那题的题解

然而考场上只得了86最后一个substask被卡了,一开始以为毒瘤出题人卡常(虽然真卡了)卡线段树,题目时限1.5s,评测机上两个点擦线1500ms左右,剩下两个点不知道。然后本地测一下都是1900+ms!机子性能已经这样了吗....结果把快读换成\(fread\),TM过了!最慢的1200+ms!!!这......无话可说,\(getchar()\)快读也卡讲究

分析:

首先最简单的处理不讲了.就是把每个点的未知数表示成\(k_i x_1 + b_i\)的形式,这DFS一遍就好了

然后观察到有一个1e3的子任务,想想暴力怎么做,我们对于操作1,相当于\((k_i+k_j)x_1+(b_i+b_j)=w\)判断一下解得情况就好了,\(O(1)\)完成;

对于操作2,我们可以发现对于\(x\)的操作,只会对\(x\)的子树中的\(k_ix_1+b_i\)形式有影响(实际上只会影响\(b_i\)),于是\(DFS\)一遍子树即可,这样总的暴力时间复杂度是\(O(nq)\)

考虑优化暴力,

我们发现瓶颈是操作2,如果将\(x\)与其父亲的边权从\(w_1\)改为\(w_2\),那么加入\(x\)本来形式是\(k_ix_1+b_i\),这时候变成了\(k_i x_1+b_i+w_2-w_1\),相当于加操作,当时在\(x\)的子树中与\(x\)的\(k_i\)(实际上显然只有-1,1两种取值)不同的点,\(b\)值却应该减去\(w_2-w_1\),所以我们将标记开成一个二元组,一个记录标记的正负,另一个记录值,重载下运算符就很方便了

struct Tag{int o;//标记的正负ll dt;Tag(){o=dt=0;}Tag(int o){o=dt=o;}Tag(int _o,ll _dt){o=_o,dt=_dt;}Tag operator +(const Tag &b)const{Tag tmp=*this;if(tmp.o==0)tmp=b;else if(b.o==0)return tmp;else {if(o!=b.o){tmp.dt=dt-b.dt;}else tmp.dt=dt+b.dt;}return tmp; }};

这样对于操作2,只用在子树加个标记就好了,因为dfs序是一段连续区间(我比较傻考场上是用树链剖分)使用线段树就好了

对于操作1,我们两次单点查询就好了,然后按暴力那样处理.

总的时间复杂度\(O(q log N)\),常数稍大

当然标算std是将深度分奇偶考虑,然后树状数组维护差分标记,时间复杂度相同但是常数小的多

代码

这是考场代码换了快读,如果想看线段树部分直接跳到\(niconicoi\)那个\(namespace\)就好了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
#define ll long long
#define ri register int
using std::min;
using std::abs;
using std::max;
inline char nc(){static char buf[100000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
template <class T>inline void read(T &x){x=0;int ne=0;char c;while(!isdigit(c=nc()))ne=c=='-';x=c-48;while(isdigit(c=nc()))x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;return ;
}
const int maxn=100005;
const int inf=0x7fffffff;
const int N=1000005;
struct Edge{int ne,to;ll dis;
}edge[N<<1];
int h[N],num_edge=1;
inline void add_edge(int f,int to,int c){edge[++num_edge].ne=h[f];edge[num_edge].to=to;edge[num_edge].dis=c;h[f]=num_edge;
}
struct Wt{int ki;ll bi;Wt(){ki=bi=0;}Wt(int _k,ll _b){ki=_k,bi=_b;}
}pt[N];
int n,q;
int fafa[N],fa_id[N];
namespace wtf{void main(){/*orz*/return ;}
}
void pre_dfs(int now,int fa){int v;int x=pt[now].ki,y=pt[now].bi;for(ri i=h[now];i;i=edge[i].ne){v=edge[i].to;if(v==fa)continue;fafa[v]=now;fa_id[v]=i;pt[v]=Wt(-x,edge[i].dis-y);pre_dfs(v,now);}return;
}
namespace qwq{void main(){int op,x,y;ll dd;ll p=edge[2].dis;while(q--){read(op),read(x),read(y);if(op==1){read(dd);if(x!=y){if(dd==p){puts("inf");}else{puts("none");}}else {if(x==1){if(dd%2)puts("none");else printf("%lld\n",dd/2);}if(x==2){ll tt=2*p-dd;if(tt%2)puts("none");else printf("%lld\n",tt/2);}}}else{p=y;}}return ;}
}
namespace task_1{void main(){int op,x,y;ll dd;int kk,bb;while(q--){read(op),read(x),read(y);if(op==1){read(dd);kk=pt[x].ki+pt[y].ki;bb=pt[x].bi+pt[y].bi;dd=dd-bb;if(kk==0){if(dd==0)puts("inf");else puts("none");}else if(dd%abs(kk)!=0)puts("none");else printf("%lld\n",dd/kk);}else {edge[fa_id[x]].dis=y;edge[fa_id[x]^1].dis=y;pre_dfs(fafa[x],fafa[fafa[x]]);}}return ;}
}
namespace niconiconi{int dep[N],top[N],son[N],size[N],dfn[N],rnk[N],tot=0;void print(ll xxx){if(!xxx)return ;print(xxx/10);putchar(xxx%10+'0');   return ;}void dfs_1(int now){int v;size[now]=1;for(ri i=h[now];i;i=edge[i].ne){v=edge[i].to;if(v==fafa[now])continue;dep[v]=dep[now]+1;dfs_1(v);size[now]+=size[v];if(!son[now]||size[son[now]]<size[v])son[now]=v;}return ;}void dfs_2(int now,int t){int v;top[now]=t;dfn[now]=++tot,rnk[tot]=now;if(!son[now])return ;dfs_2(son[now],t);for(ri i=h[now];i;i=edge[i].ne){v=edge[i].to;if(v==fafa[now]||v==son[now])continue;dfs_2(v,v);}return ;}struct Tag{int o;//标记的正负ll dt;Tag(){o=dt=0;}Tag(int o){o=dt=o;}Tag(int _o,ll _dt){o=_o,dt=_dt;}Tag operator +(const Tag &b)const{Tag tmp=*this;if(tmp.o==0)tmp=b;else if(b.o==0)return tmp;else {if(o!=b.o){tmp.dt=dt-b.dt;}else tmp.dt=dt+b.dt;}return tmp; }};Tag tag[N<<2];void build(int now,int l,int r){tag[now]=Tag(0);if(l==r){return ;}int mid=(l+r)>>1;build(now<<1,l,mid);build(now<<1|1,mid+1,r);return ;}int L,R;Tag dta;inline void pushdown(int now){if(tag[now].o==0)return ;tag[now<<1]=tag[now<<1]+tag[now];tag[now<<1|1]=tag[now<<1|1]+tag[now];tag[now]=Tag(0);return ;}void update(int now,int l,int r){if(L<=l&&r<=R){tag[now]=tag[now]+dta;return ;}int mid=(l+r)>>1;pushdown(now);if(L<=mid)update(now<<1,l,mid);if(mid<R)update(now<<1|1,mid+1,r);return ;}Wt pa,pb;int t;void query(int now,int l,int r){if(l==r){//int kkk=pt[rnk[l]].ki,bbb=pt[rnk[l]].bi;if(tag[now].o!=0){if(tag[now].o!=pt[rnk[l]].ki){pt[rnk[l]].bi-=tag[now].dt;}else{pt[rnk[l]].bi+=tag[now].dt;}tag[now]=Tag(0);}//pa.ki=pt[rnk[l]].ki;//pa.bi=pt[rnk[l]].bi;return;}int mid=(l+r)>>1;pushdown(now);if(t<=mid)query(now<<1,l,mid);else query(now<<1|1,mid+1,r);return ;}void main(){int op,x,y;ll kk,bb,dd;dep[1]=0;dfs_1(1);dfs_2(1,1);build(1,1,n);while(q--){read(op),read(x),read(y);if(op==1){read(dd);t=dfn[x];//pa=Wt(0,0);query(1,1,n);t=dfn[y];//pb=Wt(pa.ki,pa.bi),pa=Wt(0,0);query(1,1,n);//printf("%d %d %d %d\n",pa.ki,pb.ki,pa.bi,pb.bi);kk=pt[x].ki+pt[y].ki;bb=pt[x].bi+pt[y].bi;dd=dd-bb;if(kk==0){if(dd==0)puts("inf");else puts("none");}else if(dd%abs(kk)!=0)puts("none");else {if(dd==0)puts("0");else {dd=dd/kk;if(dd<0)dd=-dd,putchar('-');print(dd);puts("");}//printf("%lld\n",dd/kk);}}else {dd=edge[fa_id[x]].dis;edge[fa_id[x]].dis=edge[fa_id[x]^1].dis=y;dd=1ll*y-dd;//printf("%lld\n",dd);L=dfn[x],R=dfn[x]+size[x]-1;//t=dfn[x];pa=Wt(0,0);//query(1,1,n);pa=pt[x];//printf("%d\n",pa.ki);dta=Tag(pa.ki,dd);update(1,1,n);//update_subtree()}}return ;}
}
int main(){int x,y;freopen("equation.in","r",stdin);freopen("equation.out","w",stdout);read(n),read(q);for(ri i=2;i<=n;i++){read(x),read(y);add_edge(i,x,y);add_edge(x,i,y);}pt[1].ki=1,pt[1].bi=0;fafa[1]=0;pre_dfs(1,0);if(q==0)wtf::main();else if(n==2)qwq::main();else if(n<=2000)task_1::main();else niconiconi::main();fclose(stdin);fclose(stdout);return 0;
}

转载于:https://www.cnblogs.com/Rye-Catcher/p/9748976.html

[NOIP10.6模拟赛]2.equation题解--DFS序+线段树相关推荐

  1. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  2. 求和(dfs序+线段树)

    题意: 已知有n个节点,有n−1条边,形成一个树的结构. 给定一个根节点k,每个节点都有一个权值,节点i的权值为vi​. 给m个操作,操作有两种类型: 1 a x :表示将节点a的权值加上x 2 a ...

  3. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  4. codeforces E. Jamie and Tree LCA+dfs序+线段树

    题解: 写起来还稍微有点麻烦. dfs序+线段树可以维护子树的整体修改和查询. 因此,这道题我们要往子树上靠. 我们首先从1号点进行dfs遍历,顺便求出点的dfs序和深度,然后我们采用倍增的思想,可以 ...

  5. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  6. [CodeForces877 E. Danil and a Part-time Job]dfs序+线段树

    [CodeForces877 E.Danil and a Part-time Job]dfs序+线段树 分类:Data Structure SegMent Tree dfn 1. 题目链接 [Code ...

  7. bzoj3252攻略 贪心+dfs序+线段树

    题目链接:戳这里 3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 605  Solved: 255 [Submit][Status] ...

  8. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 339  Solved: 130 [Submit][Status][Discuss] ...

  9. dfs序+线段树 BZOJ3252 攻略

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 496  Solved: 211 [Submit][Status][Discuss] ...

最新文章

  1. python写接口自动化需要rsa加密_RSA加密,请问如何用Python实现该加密过程
  2. 笔记-项目质量管理-过程决策程序图法
  3. DbUtils使用原理详解【不懂的来】
  4. VS2010中使用sprintf出现warning C4997: 'sprintf': This function or variable may be unsafe.
  5. 关于System.FormatException异常
  6. jQuery系列:Ajax
  7. String 截取字符串#中间的文本
  8. This content should also be served over HTTPS
  9. Linux程序设计第二版练习题(第七章)
  10. 第一节 计算机硬件组成
  11. 移动前端开发和web前端开发的区别?
  12. idea-插件开发 Dialogs
  13. 基于python的招聘信息可视化系统
  14. 盲目跟风,害的是你自己
  15. latex 分页_latex中多行表格分页问题
  16. 任正非揭秘华为鸿蒙,任正非揭秘!华为鸿蒙系统,比安卓、苹果系统快,为物联网而生...
  17. mysql 转义字符 escape_mysql 的Escape转义字符串
  18. 太秀了!那个在 GitHub 用文言文编程的小哥,竟从 28 万行唐诗中找出了对称矩阵
  19. f15纸飞机折法_折纸战斗机之F15鹰式折纸战斗机的折法视频教程【折纸飞机大全】...
  20. java 改变图片的DPI

热门文章

  1. 【TensorFlow】TensorFlow函数精讲之tf.contrib.layers.l1regularizer()-12_regularizer(lambda)
  2. 一文理解图像处理之HOG特征
  3. 2018年90后薪资报告出炉:你在哪个级别???
  4. 2018值得一看的GAN论文回顾
  5. typescript和 java区别_typescript中interface和type的区别
  6. 用字典存储学生成绩查询_中考用分数评价学生音体美成绩未尝不是好事
  7. macOS 使用手册
  8. 如何建立个人博客网站
  9. 远程网络教育计算机统考试题及答案,2019年电大远程网络教育计算机应用基础统考题库真题试题附全答案...
  10. vscode 开发vue必备插件_vsCode开发vue项目必备插件