zoukankan      html  css  js  c++  java
  • 【COGS1672】难存的情缘

    【题目描述】

    一天机房的夜晚,无数人在MC里奋斗着。。。

    大家都知道矿产对于MC来说是多么的重要,但由于矿越挖越少,勇士们不得不跑到更远的地方挖矿,但这样路途上就会花费相当大的时间,导致挖矿效率底下。

    cjj提议修一条铁路,大家一致同意。

    大家都被CH分配了一些任务:

    zjmfrank2012负责绘制出一个矿道地图,这个地图包括家(当然这也是一个矿,毕竟不把家掏空我们是不会走的),和无数个矿,所以大家应该可以想出这是一个无向无环图,也就是一棵树。

    Digital_T和cstdio负责铺铁路。。所以这里没他们什么事,两位可以劳作去了。

    这个时候song526210932和RMB突然发现有的矿道会刷怪,并且怪的数量会发生变化。作为采矿主力,他们想知道从一个矿到另一个矿的路上哪一段会最困难。。。(困难值用zjm的死亡次数表示)。

    【输入格式】

    输入文件的第一行有一个整数N,代表矿的数量。矿的编号是1到N。

    接下来N-1行每行有三个整数a,b,c,代表第i号矿和第j号矿之间有一条路,在初始时这条路的困难值为c。

    接下来有若干行,每行是“CHANGE i ti”或者“QUERY a b”,前者代表把第i条路(路按所给顺序从1到M编号)的困难值修改为ti,后者代表查询a到b所经过的道路中的最大困难值。

    输入数据以一行“DONE”结束。

    【输出格式】

    对每个“QUERY”操作,输出一行一个正整数,即最大困难值。

    【分析】

    实在是让人无语的背景改变,顺便膜拜一下梦迪神牛Orzzzzzzzz。

    最基本的树链剖分。

      1 #include <cstring>
      2 #include <cmath>
      3 #include <cstdio>
      4 #include <iostream>
      5 #include <vector>
      6 const int maxn=100000+1000;
      7 using namespace std;
      8 struct Edge
      9 {
     10        int to;//所指向的 
     11        int num;//记录边的编号 
     12 };
     13 int d[maxn][3],edge=0,n,root;//用来记录边的属性 
     14 int siz[maxn],son[maxn];//子树大小和重儿子 
     15 int fa[maxn],dep[maxn],z;//父亲和深度 
     16 int w[maxn],top[maxn],tree[maxn];
     17 char str[55];
     18 vector<Edge>map[maxn];
     19 
     20 inline void init();
     21 inline void work();
     22 inline void dfs(int u);//第一次DFS 
     23 inline void addEdge(int u,int v);//加边 
     24 inline void make_tree(int u,int tp);//第二次DFS 
     25 inline void update(int root,int l,int r,int num,int c);//c是变更值 
     26 inline int read();//读入函数 
     27 inline int find(int a,int b);
     28 inline int maxi(int root,int l,int r,int l1,int l2);
     29 
     30 
     31 inline void addEdge(int u,int v)
     32 {
     33      edge++;
     34      map[u].push_back((Edge){v,edge});
     35 }
     36 inline void dfs(int u)//第一次dfs 
     37 {
     38      int i;
     39      siz[u]=1;
     40      son[u]=0;
     41      for (i=0;i<map[u].size();i++)
     42      {
     43          int v=map[u][i].to;
     44          if (v!=fa[u])
     45          {
     46              fa[v]=u;//更新父亲 
     47              dep[v]=dep[u]+1;//更新深度 
     48              dfs(v);
     49              if (siz[v]>siz[son[u]]) son[u]=v;
     50              siz[u]+=siz[v];
     51          }
     52      }
     53 }
     54 //建树操作 
     55 inline void make_tree(int u,int tp)
     56 {
     57      int i;
     58      w[u]=++z;
     59      top[u]=tp;
     60      if (son[u]!=0) make_tree(son[u],top[u]);//优先走重儿子
     61      for (i=0;i<map[u].size();i++)
     62      {
     63          int v=map[u][i].to;
     64          if (v!=son[u] && v!=fa[u])
     65          make_tree(v,v);
     66      } 
     67 }
     68 //修改操作 
     69 inline void update(int root,int l,int r,int num,int c)
     70 {
     71      if (num>r || num<l) return;
     72      if (l==r) {tree[root]=c;return;} 
     73      int mid=(l+r)/2;
     74      //递归修改 
     75      update(root*2,l,mid,num,c);
     76      update(root*2+1,mid+1,r,num,c);
     77      tree[root]=max(tree[root*2],tree[root*2+1]);
     78 } 
     79 inline void init()
     80 {
     81      int i;
     82      scanf("%d",&n);
     83      root=(1+n)/2;//随机根 
     84      fa[root]=z=dep[root]=edge=0;
     85      memset(d,0,sizeof(d));
     86      memset(tree,0,sizeof(tree));
     87      for (i=1;i<n;i++)
     88      {
     89          int u,v,w;
     90          scanf("%d%d%d",&u,&v,&w);
     91          d[i][0]=u;d[i][1]=v;d[i][2]=w;
     92          addEdge(u,v);//加无向边 
     93          addEdge(v,u);
     94      }
     95      dfs(root);//第一次
     96      make_tree(root,root);
     97      for (i=1;i<n;i++)
     98      {
     99          if (dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);//交换
    100          update(1,1,z,w[d[i][1]],d[i][2]);//开始加边 
    101      } 
    102      return;
    103 }
    104 inline int read()
    105 {
    106      scanf("%s",str);
    107      if (str[0]=='D') 
    108      return 0;
    109      //printf("%s
    ",str);
    110      return 1;
    111 } 
    112 inline int maxi(int root,int l,int r,int l1,int r1)
    113 {
    114     if (l1>r || r1<l) return 0;//边界条件
    115     if (l1<=l && r<=r1) return tree[root];
    116     int mid=(l+r)/2;
    117     return max(maxi(root*2,l,mid,l1,r1),maxi(root*2+1,mid+1,r,l1,r1)); 
    118 }
    119 //进行从a到b的询问 
    120 inline int find(int a,int b)
    121 {
    122      int f1=top[a],f2=top[b],temp=0;
    123      while (f1!=f2)//LCA
    124      {
    125            if (dep[f1]<dep[f2])//统一深度 
    126            {
    127                swap(f1,f2);
    128                swap(a,b);
    129            } 
    130            temp=max(temp,maxi(1,1,z,w[f1],w[a]));
    131            a=fa[f1];f1=top[a];//向上传递 
    132      } 
    133      if (a==b) return temp;
    134      if (dep[a]>dep[b]) swap(a,b);
    135      return max(temp,maxi(1,1,z,w[son[a]],w[b]));
    136 }
    137 inline void work()
    138 {
    139      int a,b;
    140      while (read())
    141      {
    142            scanf("%d%d",&a,&b);
    143            if (str[0]=='Q') printf("%d
    ",find(a,b));
    144            else update(1,1,z,w[d[a][1]],b);
    145      }
    146      return;
    147 }
    148 int main()
    149 {
    150     //文件操作 
    151     freopen("qtree.in","r",stdin);
    152     freopen("qtree.out","w",stdout);
    153     init();//初始化
    154     work();    
    155     return 0;
    156 }
  • 相关阅读:
    编译Filebeat源码
    一些常用的shell写法
    设置tomcat默认访问的项目
    修改Linux软件源
    k8s创建使用nfs的StorageClass
    使用NFS服务实现文件共享
    idea配置代码注释模板
    redis cluster(集群)模式的创建方式
    etcd简单测试类java版
    Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
  • 原文地址:https://www.cnblogs.com/hoskey/p/3830341.html
Copyright © 2011-2022 走看看