zoukankan      html  css  js  c++  java
  • [loj2245]魔法森林

    枚举携带的"A型守护精灵"数$A_{0}$,那么即只能经过$A_{i}le A_{0}$的边,并最小化1到$n$路径上最大的$B_{i}$

    将所有边按照$A_{i}$从小到大排序,那么前者即不断加入边,后者通过LCT维护$B_{i}$的最小生成树即可

    具体的,将每一条边拆成一个点,向对应的两端点连边,加入一条边时查询对应环(若不产生环则直接加入)上$B_{i}$最大的边并替换即可

    时间复杂度为$o(mlog m)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 150005
      4 struct Data{
      5     int x,y,a,b;
      6     bool operator < (const Data &k)const{
      7         return a<k.a;
      8     }
      9 }e[N];
     10 multiset<int>S;
     11 int n,m,ans,st[N],fa[N],sz[N],rev[N],val[N],mx[N],ch[N][2];
     12 int which(int k){
     13     return ch[fa[k]][1]==k;
     14 }
     15 int check(int k){
     16     return ch[fa[k]][which(k)]==k;
     17 }
     18 int get_max(int x,int y){
     19     if (e[x].b>e[y].b)return x;
     20     return y;
     21 }
     22 void upd(int k){
     23     rev[k]^=1;
     24     swap(ch[k][0],ch[k][1]);
     25 }
     26 void up(int k){
     27     sz[k]=sz[ch[k][0]]+sz[ch[k][1]]+1;
     28     mx[k]=get_max(get_max(mx[ch[k][0]],mx[ch[k][1]]),val[k]);
     29 }
     30 void down(int k){
     31     if (rev[k]){
     32         if (ch[k][0])upd(ch[k][0]);
     33         if (ch[k][1])upd(ch[k][1]);
     34         rev[k]=0;
     35     }
     36 }
     37 void rotate(int k){
     38     int f=fa[k],g=fa[f],p=which(k);
     39     fa[k]=g;
     40     if (check(f))ch[g][which(f)]=k;
     41     fa[ch[k][p^1]]=f,ch[f][p]=ch[k][p^1];
     42     fa[f]=k,ch[k][p^1]=f;
     43     up(f),up(k);
     44 }
     45 void splay(int k){
     46     for(int i=k;;i=fa[i]){
     47         st[++st[0]]=i;
     48         if (!check(i))break;
     49     }
     50     while (st[0])down(st[st[0]--]);
     51     for(int i=fa[k];check(k);i=fa[k]){
     52         if (check(i)){
     53             if (which(i)==which(k))rotate(i);
     54             else rotate(k);
     55         }
     56         rotate(k);
     57     }
     58 }
     59 void access(int k){
     60     int lst=0;
     61     while (k){
     62         splay(k);
     63         ch[k][1]=lst,up(k);
     64         lst=k,k=fa[k];
     65     }
     66 }
     67 void make_root(int k){
     68     access(k);
     69     splay(k);
     70     upd(k);
     71 }
     72 int find_root(int k){
     73     access(k);
     74     splay(k);
     75     while (ch[k][0]){
     76         down(k);
     77         k=ch[k][0];
     78     }
     79     splay(k);
     80     return k;
     81 }
     82 void add(int x,int y){
     83     make_root(x);
     84     make_root(y);
     85     fa[y]=x;
     86 }
     87 void del(int x,int y){
     88     make_root(x);
     89     access(y);
     90     splay(x);
     91     fa[y]=ch[x][1]=0;
     92     up(x);
     93 }
     94 int query(int x,int y){
     95     make_root(x);
     96     if (find_root(y)!=x)return -1;
     97     return mx[x];
     98 }
     99 int main(){
    100     scanf("%d%d",&n,&m);
    101     for(int i=1;i<=m;i++)scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].a,&e[i].b);
    102     sort(e+1,e+m+1);
    103     for(int i=1;i<=m;i++)val[i+n]=mx[i+n]=i;
    104     for(int i=1;i<=m;i++)add(e[i].x,i+n);
    105     ans=1e9;
    106     for(int i=1;i<=m;i++){
    107         int s=query(e[i].y,i+n);
    108         if (s!=i){
    109             if (s>0)del(e[s].y,s+n);
    110             add(e[i].y,i+n);
    111         }
    112         s=query(1,n);
    113         if (s>0)ans=min(ans,e[i].a+e[s].b);
    114     }
    115     if (ans==1e9)ans=-1;
    116     printf("%d
    ",ans);
    117     return 0;
    118 } 
    View Code
  • 相关阅读:
    【Docker】解析器指令之 escape
    【Docker】解析器指令之 syntax
    【Docker】Dockerfile 解析器指令
    【Docker】Dockerfile 格式
    【Docker】Dockerfile 介绍
    【Docker】Spring Boot 和 Docker
    【Docker】理解 Docker 中的 OverlayFS
    【Docker】使用 OverlayFS 存储驱动
    【Docker】选择存储驱动
    kuangbin专题 专题一 简单搜索 Fire! UVA
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15210658.html
Copyright © 2011-2022 走看看