zoukankan      html  css  js  c++  java
  • [loj2469]最小方差生成树

    2018年论文题

    约定:令点集$V=[1,n]$、边集$E=[1,m]$,记$m$条边依次为$e_{i}=(x_{i},y_{i},c_{i})$(其中$1le ile m$),将其按照$c_{i}$从小到大排序,即不妨假设有$c_{1}le c_{2}le...le c_{m}$


     先来考虑$T=1$的情况,即如何求最小方差生成树

    题意即求$min_{E_{T}subseteq E,E_{T}为生成树}frac{sum_{xin E_{T}}(mu-c_{x})^{2}}{n-1}$(其中$mu=frac{sum_{xin E_{T}}c_{x}}{n-1}$)

    考虑函数$f(x)=frac{sum_{i=1}^{n-1}(x-a_{i})^{2}}{n-1}$,根据二次函数的性质其最小值恰在$x=frac{sum_{i=1}^{n-1}a_{i}}{n-1}$处取到

    换言之,有$frac{sum_{xin E_{T}}(mu-c_{x})^{2}}{n-1}=min_{muin R}frac{sum_{xin E_{T}}(mu-c_{x})^{2}}{n-1}$

    代入后交换顺序,即$min_{muin R}frac{min_{E_{T}subseteq E,E_{T}为生成树}sum_{xin E_{T}}(mu-c_{x})^{2}}{n-1}$,其中分子即以$(mu-c_{i})^{2}$为边权求最小生成树


     令$E_{chi}$表示$mu=chi$时最小生成树的边集,为了使其能被唯一确定,求最小生成树时将$e_{i}$按照$(mu-c_{i})^{2}$和$i$这两个关键字从小到大排序(假设用kruskal求最小生成树)

    将问题从边的角度来考虑,显然$iin E_{chi}$当且仅当$mu=chi$时排在$e_{i}$前面的边不能使$x_{i}$和$y_{i}$连通

    不妨假设$chi le c_{i}$,那么$e_{j}$排在$e_{i}$前面当且仅当$2chi-c_{i}le c_{j}<c_{i}$或$c_{j}=c_{i}$且$j<i$

    显然$chi$的范围具有单调性,即只需要不断加入$e_{i-1},e_{i-2},...$直至$x_{i}$和$y_{i}$连通,设最后一条边加入的是$e_{k}$,那么满足$chile c_{i}$且$iin E_{chi}$的$chi$的范围为$frac{c_{i}+c_{k}}{2}<chile c_{i}$

    (特别的,若最后仍未连通即令$c_{k}=-infty$)


     显然,使用LCT维护$i$之前的边(不包括$i$)关于编号的最大生成树,询问的也即该生成树从$x_{i}$到$y_{i}$路径上的编号最小的边,时间复杂度为$o(mlog m)$

    关于$chi>c_{i}$且$iin E_{chi}$的范围,可以类似地求出,但会多一个2的常数,实际上可以避免

    记$l_{i}$为最大的$k$满足$e[k,i)$能使$x_{i}$和$y_{i}$连通,$r_{i}$为最小的$k$满足$e(i,k]$能使$x_{i}$和$y_{i}$连通

    结论:若$L_{i}$存在,则$R_{L_{i}}=i$;若$R_{i}$存在,则$R_{L_{i}}=i$

    记$k=L_{i}$,则$e[k,i)$能使$x_{i}$和$y_{i}$连通,那么$e(k,i]$即能使$x_{k}$和$y_{k}$连通,也即$R_{k}le i$

    另一方面,如果$e(k,i)$就能使$x_{k}$和$y_{k}$连通,那么$e[k,i)$与$e(k,i)$的连通性应该相同(因为$(x_{k},y_{k})$不影响连通性),也即$l_{i}$可以为$k+1$,与$L_{i}$的最大性矛盾,因此$R_{k}ge i$

    综上,即有$R_{k}=i$,类似地也可以得到后者

    由此即可线性求出$R_{i}$($L_{i}$之前已求出),根据后半部分,未被覆盖的$R_{i}$即为无解


     进而将两个范围求并,即得到满足$iin E_{chi}$的$chi$的范围为$(frac{c_{L_{i}}+c_{i}}{2},frac{c_{i}+c_{R_{i}}}{2}]$

    此时,$E_{chi}$即对应范围包含$chi$的$i$所组成的集合(注意这个范围是充分必要的),那么只需要通过离散和差分对每一个位置维护$S_{1}=sum c_{i}$和$S_{2}=sum c^{2}_{i}$的和即可(方差即$frac{(n-1)S_{2}-S_{1}^{2}}{(n-1)^{2}}$)

    另外,需要考虑实数的位置如何处理,可以将权值乘2并用两整数中间的部分代替该段实数

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


     下面考虑$T=2$的情况,即如何对删去每一条边后的图求最小方差生成树

    通过$T=1$时的做法,即可在$o(mlog m)$的时间内求出最小方差生成树即其方案

    显然删除方案以外的边是不影响答案的,因此只需要考虑方案中的$n-1$条边,那么对这$n-1$条边暴力删除并再求一次最小方差生成树,即得到一个$o(nmlog m)$的做法,但无法通过

    假设删除的边是$e_{del}$,那么$L_{i}$发生变化的边必然都在$e(del,m]$这些边关于编号的最小生成树上,因为如果$e_{i}$不在最小生成树上,即等价于$e(del,i)$能使$x_{i}$和$y_{i}$连通,显然删去$e_{del}$没有意义

    显然这样的边只有$o(n)$条,但求最大生成树仍要从前往后依次加边,复杂度并没有优化


     记$T_{1}$为$e[1,del)$的关于编号的最大生成树,$T_{2}$为$e(del,m]$的关于编号的最小生成树

    初始令$T=T_{2}$,并将$T_{1}$中的边的按编号从大到小依次加入$T$,并继续维护$T$为最小生成树

    结论:假设在加入$e_{i}$时删除了$e_{j}$,则有$L_{j}=i$

    显然$x_{j}$到$y_{j}$路径上所有边编号都在$[i,j)$中,因此也即$L_{j}ge i$

    同时如果$L_{j}>i$,那么不难得到$x_{i}$和$y_{i}$可以通过$e(i,del)$连通,与$e_{i}$在$T_{1}$上矛盾

    通俗的来说,求$e[1,i)$的最大生成树上在$e_{del}$之前的边一定在$e[1,del)$的最大生成树上,并且$e_{del}$之后的边一定不会作为$l_{i}$,因此只关心于这类边的连通性

    另外,对于$T_{1}$中最终仍没有被删除的边$e_{i}$,则$L_{i}$无解

    此时,重新计算$L_{i}$和$R_{i}$的时间复杂度即降为$o(n^{2}log m)$


     下面,给出一些关于实现上的细节:

    1.关于LCT的清空,可以维护一个当前的边集(用标记数组即可),那么清空时遍历所有边并用删掉即可,由于删除的复杂度与加入时相同,因此相当于仅为$o(m)$,总复杂度也即$o(nm)$

    2.关于$T_{1}$和$T_{2}$需要在初始预处理,在求最小/最大生成树过程中,当访问到的边是在方案中时,就将当前LCT中维护的边集$o(m)$找出即可,总复杂度也为$o(nm)$

    3.关于离散和差分,重新暴力排序+二分复杂度又会退化为$o(nmlog m)$,注意到总共只会额外产生$o(n^{2})$个位置,将这些位置预处理出来并排序,然后将初始的差分数组记录

    此时,每一次即对差分数组的$o(n)$个位置修改,总复杂度也即$o(mlog m+n^{2}log m+nm)$

    时间复杂度为$o(mlog m+n^{2}log m+nm)$,可以通过


     然而,注意到答案的范围为$n^{2}C^{2}$,而在子任务8该值达到了$10^{41}$的级别,无法使用__int128存储

    由此,即需要在差分的过程中使用高精度乘法求$S_{1}^{2}$(显然其他都不需要高精度),设高精度的常数为$o(P)$,时间复杂度即变为$o(mlog n+n^{2}log m+Pnm)$,无法通过

    下面,具体的来描述差分的过程——

    令$N=n^{2}+m$,差分数组即是两个长度为$N$的序列,初始为分别为$Delta S_{1}(i)$和$Delta S_{2}(i)$(下标为$[1,N]$)

    每一次查询,修改其中$o(n)$​个位置的值(无后效性),并查询
    $$
    min_{1le ile N}left((n-1)sum_{j=1}^{i}Delta S_{2}(j)-(sum_{j=1}^{i}Delta S_{1}(i))^{2} ight)
    $$
    (其余部分的复杂度显然都可以做到$o(mlog m+n^{2}log m+nm+Pn^{2})$,其中$o(Pn^{2})$为计算修改的值)


     预处理出前缀和$S_{1}(i)=sum_{j=1}^{i}Delta S_{1}(j),S_{2}(i)=sum_{j=1}^{i}Delta S_{2}(j)$(对于初始状态),每一次修改的$o(n)$个位置即将原序列划分为$o(n)$段,并对每一段$[l,r]$分别求出$iin [l,r]$的最小值

    (其中$[l,r]$不包含修改的位置,修改的位置直接暴力$o(Pn^{2})$计算即可)

    对于$[l,r]$​,求出此次修改对$iin [l,r]$​的$S_{1}(i)$​和$S_{2}(i)$​的变化量,分别记作$Delta s_{1}$​和$Delta s_{2}$​(显然对所有位置都相同),那么$iin [l,r]$​的最小值即
    $$
    min_{i=l}^{r}left((n-1)(S_{2}(i)+Delta s_{2})-(S_{1}(i)+Delta s_{1})^{2} ight)
    $$
    并对于其中一段$[l,r]$,求出其之前的本次修改的变化量$Delta s_{1}$和$Delta s_{2}$

    简单化简,即
    $$
    min_{i=l}^{r}left(-2Delta s_{1}S_{1}(i)+((n-1)S_{2}(i)-S_{1}^{2}(i)) ight)+left((n-1)Delta s_{2}-Delta s_{1}^{2} ight)
    $$


     此时,问题即可以看作求经过$(2S_{1}(i),(n-1)S_{2}(i)-S_{1}^{2}(i))$且斜率为$-Delta s_{1}$的直线的最小截距

    求出$[l,r]$中的点所构成的下凸壳,二分找到其中第一个斜率大于等于$-Delta s_{1}$的线段的左端点即为最小值

    可以使用线段树来维护,预处理时先将所有点按照$x$坐标排序,并依次加入线段树上区间包含其的$o(log N)$个凸包中,那么预处理的时间复杂度即为$o(PNlog N)$

    查询时将$[l,r]$划分为$o(log N)$个区间,再在每一个区间对应的线段树凸包上二分,将所有最小值取$min$即可,那么查询的时间复杂度为$o(Pn^{2}log^{2}N)$

    进一步的,可以将线段树每一个区间对应的凸包上的询问离线并排序,再利用单调性做到线性即可

    关于排序,再将所有$-Delta s_{1}$排序再依次加入,注意到外部仅有$o(n^{2})$个,因此查询复杂度降为$o(Pn^{2}log N)$

    时间复杂度为$o(nm+PNlog N)$,可以通过

    (代码只优化到$o(mlog m+n^{2}log m+Pnm)$,但已经可以通过)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 305
      4 #define M 100005
      5 #define base 1000000000
      6 #define ll long long
      7 #define pli pair<ll,int>
      8 #define fi first
      9 #define se second
     10 struct Data{
     11     int x,y,id;
     12     ll z;
     13     bool operator < (const Data &k)const{
     14         return z<k.z;
     15     }
     16 }e[M];
     17 struct Num{
     18     int p,len;
     19     ll a[5];
     20     Num(ll k=0){
     21         p=(k<0),len=0;
     22         memset(a,0,sizeof(a));
     23         k=abs(k);
     24         while (k){
     25             a[len++]=k%base;
     26             k/=base;
     27         }
     28     }
     29 }Check,S1,S2,ans,z1[M],z2[M],dS1[M<<1],dS2[M<<1],Ans[M];
     30 vector<int>T1[M],T2[M];
     31 vector<pli>v0,v[M];
     32 int n,m,T,q,L0[M],R0[M],L[M],R[M],vis0[M];
     33 ll Pos[M<<1];
     34 namespace IO{
     35     int num[100];
     36     ll x;
     37     char c;
     38     ll read(){
     39         x=0,c=getchar();
     40         while ((c<'0')||(c>'9'))c=getchar();
     41         while ((c>='0')&&(c<='9')){
     42             x=x*10+c-'0';
     43             c=getchar();
     44         }
     45         return x;
     46     }
     47     void write(Num x,char c=''){
     48         if (x.p)putchar('-');
     49         for(int i=0;i<x.len;i++)
     50             for(int j=0;j<9;j++){
     51                 num[++num[0]]=x.a[i]%10;
     52                 x.a[i]/=10;
     53             }
     54         while ((num[0])&&(!num[num[0]]))num[0]--;
     55         if (!num[0])putchar('0');
     56         while (num[0])putchar(num[num[0]--]+'0');
     57         putchar(c);
     58     }
     59 };
     60 namespace Calc{
     61     int cmp(Num x,Num y){
     62         if (x.len!=y.len){
     63             if (x.len<y.len)return -1;
     64             return 1;
     65         }
     66         for(int i=x.len-1;i>=0;i--)
     67             if (x.a[i]!=y.a[i]){
     68                 if (x.a[i]<y.a[i])return -1;
     69                 return 1;
     70             }
     71         return 0;
     72     }
     73     Num min(Num x,Num y){
     74         if (cmp(x,y)<0)return x;
     75         return y;
     76     }
     77     Num add(Num x,Num y){
     78         Num ans;
     79         if (x.p==y.p){
     80             ans.p=x.p,ans.len=max(x.len,y.len);
     81             for(int i=0;i<ans.len;i++){
     82                 ans.a[i]+=x.a[i]+y.a[i];
     83                 if (ans.a[i]>=base){
     84                     ans.a[i]-=base;
     85                     ans.a[i+1]++;
     86                 }
     87             }
     88             if ((ans.len<5)&&(ans.a[ans.len]))ans.len++;
     89             return ans;
     90         }
     91         if (cmp(x,y)<0)swap(x,y);
     92         ans.p=x.p,ans.len=x.len;
     93         for(int i=0;i<ans.len;i++){
     94             ans.a[i]+=x.a[i]-y.a[i];
     95             if (ans.a[i]<0){
     96                 ans.a[i]+=base;
     97                 ans.a[i+1]--;
     98             }
     99         }
    100         while ((ans.len)&&(!ans.a[ans.len-1]))ans.len--;
    101         return ans;
    102     }
    103     Num dec(Num x,Num y){
    104         y.p^=1;
    105         return add(x,y);
    106     }
    107     Num mul(Num x,Num y){
    108         Num ans;
    109         ans.p=(x.p^y.p),ans.len=x.len+y.len-1;
    110         for(int i=0;i<x.len;i++)
    111             for(int j=0;j<y.len;j++){
    112                 ans.a[i+j]+=x.a[i]*y.a[j];
    113                 ans.a[i+j+1]+=ans.a[i+j]/base;
    114                 ans.a[i+j]%=base;
    115             }
    116         if ((ans.len<5)&&(ans.a[ans.len]))ans.len++;
    117         return ans;
    118     }
    119 };
    120 namespace LCT{
    121     int vis[M],st[M<<1],fa[M<<1],mn[M<<1],mx[M<<1],rev[M<<1],ch[M<<1][2];
    122     int which(int k){
    123         return ch[fa[k]][1]==k;
    124     }
    125     bool check(int k){
    126         return ch[fa[k]][which(k)]==k;
    127     }
    128     void upd(int k){
    129         rev[k]^=1;
    130         swap(ch[k][0],ch[k][1]);
    131     } 
    132     void up(int k){
    133         mn[k]=min(mn[ch[k][0]],mn[ch[k][1]]);
    134         mx[k]=max(mx[ch[k][0]],mx[ch[k][1]]);
    135         if (k>n){
    136             mn[k]=min(mn[k],k-n);
    137             mx[k]=max(mx[k],k-n); 
    138         }
    139     }
    140     void down(int k){
    141         if (rev[k]){
    142             if (ch[k][0])upd(ch[k][0]);
    143             if (ch[k][1])upd(ch[k][1]);
    144             rev[k]=0;
    145         }
    146     }
    147     void rotate(int k){
    148         int f=fa[k],g=fa[f],p=which(k);
    149         fa[k]=g;
    150         if (check(f))ch[g][which(f)]=k;
    151         fa[ch[k][p^1]]=f,ch[f][p]=ch[k][p^1];
    152         fa[f]=k,ch[k][p^1]=f;
    153         up(f),up(k);
    154     }
    155     void splay(int k){
    156         for(int i=k;check(i);i=fa[i])st[++st[0]]=fa[i];
    157         while (st[0])down(st[st[0]--]);
    158         down(k);
    159         for(int i=fa[k];check(k);i=fa[k]){
    160             if (check(i)){
    161                 if (which(i)==which(k))rotate(i);
    162                 else rotate(k);
    163             }
    164             rotate(k);
    165         }
    166     }
    167     void access(int k){
    168         int lst=0;
    169         while (k){
    170             splay(k);
    171             ch[k][1]=lst,up(k);
    172             lst=k,k=fa[k];
    173         }
    174     }
    175     void make_root(int k){
    176         access(k);
    177         splay(k);
    178         upd(k);
    179     }
    180     int find_root(int k){
    181         access(k);
    182         splay(k);
    183         while (ch[k][0]){
    184             down(k);
    185             k=ch[k][0];
    186         }
    187         splay(k);
    188         return k;
    189     }
    190     void add(int x,int y){
    191         make_root(x);
    192         make_root(y);
    193         fa[y]=x;
    194     }
    195     void del(int x,int y){
    196         make_root(x);
    197         access(y);
    198         splay(x);
    199         fa[y]=ch[x][1]=0,up(x);
    200     }
    201     int query_min(int x,int y){
    202         make_root(x);
    203         if (find_root(y)!=x)return 0;
    204         return mn[x];
    205     }
    206     int query_max(int x,int y){
    207         make_root(x);
    208         if (find_root(y)!=x)return 0;
    209         return mx[x];
    210     }
    211     int add_min(int id){
    212         int pos=query_min(e[id].y,id+n);
    213         if (pos){
    214             vis[0]--,vis[pos]=0;
    215             LCT::del(e[pos].y,pos+n);
    216         }
    217         vis[0]++,vis[id]=1;
    218         LCT::add(e[id].y,id+n);
    219         return pos;
    220     }
    221     int add_max(int id){
    222         int pos=query_max(e[id].y,id+n);
    223         if (pos){
    224             vis[0]--,vis[pos]=0;
    225             LCT::del(e[pos].y,pos+n);
    226         }
    227         vis[0]++,vis[id]=1;
    228         LCT::add(e[id].y,id+n);
    229         return pos;
    230     }
    231     void init(){
    232         mn[0]=0x3f3f3f3f,mx[0]=0;
    233         for(int i=1;i<=n+m;i++){
    234             fa[i]=rev[i]=ch[i][0]=ch[i][1]=0;
    235             up(i);
    236         }
    237         for(int i=1;i<=m;i++)add(e[i].x,i+n);
    238     }
    239     void clear(){
    240         for(int i=1;i<=m;i++)
    241             if (vis[i]){
    242                 LCT::del(e[i].y,i+n);
    243                 vis[0]--,vis[i]=0;
    244             }
    245     }
    246 };
    247 void get_LR(){
    248     memset(L0,0,sizeof(L0));
    249     memset(R0,0,sizeof(R0));
    250     LCT::clear();
    251     for(int i=1;i<=m;i++){
    252         L0[i]=LCT::add_min(i);
    253         if (L0[i])R0[L0[i]]=i;
    254     }
    255 }
    256 void get_T12(){
    257     LCT::clear();
    258     for(int i=1;i<=m;i++){
    259         if (vis0[i]){
    260             for(int j=m;j;j--)
    261                 if (LCT::vis[j])T1[i].push_back(j);
    262         }
    263         LCT::add_min(i);
    264     }
    265     LCT::clear();
    266     for(int i=m;i;i--){
    267         if (vis0[i]){
    268             for(int j=1;j<=m;j++)
    269                 if (LCT::vis[j])T2[i].push_back(j); 
    270         }
    271         LCT::add_max(i);
    272     }
    273 }
    274 void get_v(){
    275     v0.clear();
    276     for(int i=1;i<=m;i++){
    277         if (!L0[i])v0.push_back(make_pair(0,i));
    278         else v0.push_back(make_pair((e[L0[i]].z+e[i].z<<1)+1,i));
    279         if (R0[i])v0.push_back(make_pair((e[i].z+e[R0[i]].z<<1)+1,-i));
    280     }
    281 }
    282 void upd_LR(int k){
    283     LCT::clear();
    284     memcpy(L,L0,sizeof(L));
    285     L[k]=k;
    286     for(int i=0;i<T2[k].size();i++){
    287         L[T2[k][i]]=0;
    288         LCT::add_max(T2[k][i]);
    289     }
    290     for(int i=0;i<T1[k].size();i++){
    291         int pos=LCT::add_max(T1[k][i]);
    292         if (pos)L[pos]=T1[k][i];
    293     }
    294     memset(R,0,sizeof(R));
    295     for(int i=1;i<=m;i++)
    296         if (L[i])R[L[i]]=i;
    297 }
    298 void upd_v(int k){
    299     T1[k].push_back(k),T2[k].push_back(k);
    300     for(int i=0;i<T1[k].size();i++){
    301         int pos=T1[k][i];
    302         if (R0[pos])v[k].push_back(make_pair((e[pos].z+e[R0[pos]].z<<1)+1,pos));
    303         if (R[pos]){
    304             v0.push_back(make_pair((e[pos].z+e[R[pos]].z<<1)+1,0));
    305             v[k].push_back(make_pair((e[pos].z+e[R[pos]].z<<1)+1,-pos));
    306         }
    307     }
    308     for(int i=0;i<T2[k].size();i++){
    309         int pos=T2[k][i];
    310         if (!L0[pos])v[k].push_back(make_pair(0,-pos));
    311         else v[k].push_back(make_pair((e[L0[pos]].z+e[pos].z<<1)+1,-pos));
    312         if (!L[pos]){
    313             v0.push_back(make_pair(0,0));
    314             v[k].push_back(make_pair(0,pos));
    315         }
    316         else{
    317             v0.push_back(make_pair((e[L[pos]].z+e[pos].z<<1)+1,0));
    318             v[k].push_back(make_pair((e[L[pos]].z+e[pos].z<<1)+1,pos));
    319         }
    320     }
    321 }
    322 void unique(){
    323     sort(v0.begin(),v0.end());
    324     q=0;
    325     for(int i=0;i<v0.size();i++){
    326         if ((!i)||(v0[i].fi!=v0[i-1].fi))Pos[++q]=v0[i].fi;
    327         int pos=abs(v0[i].se);
    328         if (v0[i].se>0)dS1[q]=Calc::add(dS1[q],z1[pos]),dS2[q]=Calc::add(dS2[q],z2[pos]);
    329         else dS1[q]=Calc::dec(dS1[q],z1[pos]),dS2[q]=Calc::dec(dS2[q],z2[pos]);
    330     }
    331 }
    332 void calc(){
    333     sort(v0.begin(),v0.end());
    334     S1=S2=0,ans.len=10;
    335     for(int i=0;i<v0.size();i++){
    336         int pos=abs(v0[i].se);
    337         if (v0[i].se>0)S1=Calc::add(S1,z1[pos]),S2=Calc::add(S2,z2[pos]);
    338         else S1=Calc::dec(S1,z1[pos]),S2=Calc::dec(S2,z2[pos]);
    339         if ((i==v0.size())||(v0[i].fi!=v0[i+1].fi)){
    340             if (!v0[i].fi)Check=S1;
    341             ans=Calc::min(ans,Calc::dec(S2,Calc::mul(S1,S1)));
    342         }
    343     }
    344     S1=S2=0;
    345     memset(vis0,0,sizeof(vis0));
    346     for(int i=0;i<v0.size();i++){
    347         int pos=abs(v0[i].se);
    348         vis0[pos]^=1;
    349         if (v0[i].se>0)S1=Calc::add(S1,z1[pos]),S2=Calc::add(S2,z2[pos]);
    350         else S1=Calc::dec(S1,z1[pos]),S2=Calc::dec(S2,z2[pos]);
    351         if (((i==v0.size())||(v0[i].fi!=v0[i+1].fi))&&(!Calc::cmp(ans,Calc::dec(S2,Calc::mul(S1,S1)))))break;
    352     }
    353 }
    354 void calc(int k){
    355     for(int i=0;i<v[k].size();i++){
    356         int q0=lower_bound(Pos+1,Pos+q+1,v[k][i].fi)-Pos,pos=abs(v[k][i].se);
    357         if (v[k][i].se>0)dS1[q0]=Calc::add(dS1[q0],z1[pos]),dS2[q0]=Calc::add(dS2[q0],z2[pos]);
    358         else dS1[q0]=Calc::dec(dS1[q0],z1[pos]),dS2[q0]=Calc::dec(dS2[q0],z2[pos]);
    359     }
    360     if (Calc::cmp(dS1[1],Check)<0){
    361         ans=-1;
    362         return;
    363     } 
    364     S1=S2=0,ans.len=10;
    365     for(int i=1;i<=q;i++){
    366         S1=Calc::add(S1,dS1[i]),S2=Calc::add(S2,dS2[i]);
    367         ans=Calc::min(ans,Calc::dec(S2,Calc::mul(S1,S1)));
    368     }
    369     for(int i=0;i<v[k].size();i++){
    370         int q0=lower_bound(Pos+1,Pos+q+1,v[k][i].fi)-Pos,pos=abs(v[k][i].se);
    371         if (v[k][i].se<0)dS1[q0]=Calc::add(dS1[q0],z1[pos]),dS2[q0]=Calc::add(dS2[q0],z2[pos]);
    372         else dS1[q0]=Calc::dec(dS1[q0],z1[pos]),dS2[q0]=Calc::dec(dS2[q0],z2[pos]);
    373     }
    374 }
    375 int main(){
    376     n=IO::read(),m=IO::read(),T=IO::read();
    377     for(int i=1;i<=m;i++){
    378         e[i].x=IO::read(),e[i].y=IO::read(),e[i].z=IO::read();
    379         e[i].id=i;
    380     }
    381     sort(e+1,e+m+1);
    382     LCT::init();
    383     for(int i=1;i<=m;i++){
    384         z1[i]=e[i].z;
    385         z2[i]=Calc::mul(n-1,Calc::mul(z1[i],z1[i]));
    386     }
    387     get_LR();
    388     if (LCT::vis[0]!=n-1){
    389         if (T==1)IO::write(-1,'
    ');
    390         else{
    391             for(int i=1;i<=m;i++)IO::write(-1,'
    ');
    392         }
    393         return 0;
    394     }
    395     get_v(),calc();
    396     if (T==1){
    397         IO::write(ans,'
    ');
    398         return 0;
    399     }
    400     for(int i=1;i<=m;i++)
    401         if (!vis0[i])Ans[e[i].id]=ans;
    402     get_T12();
    403     for(int i=1;i<=m;i++)
    404         if (vis0[i])upd_LR(i),upd_v(i);
    405     unique();
    406     for(int i=1;i<=m;i++)
    407         if (vis0[i]){
    408             calc(i);
    409             Ans[e[i].id]=ans;
    410         }
    411     for(int i=1;i<=m;i++)IO::write(Ans[i],'
    ');
    412     return 0;
    413 }
    View Code
  • 相关阅读:
    在宝塔中升级mysql版本
    测试winform程序到树莓派运行
    winserver2012远程桌面进入只有CMD窗口,无桌面解决方法
    一七年春末
    Linux 上通过rpm安装mysql
    Linux 上关于iptables
    Linux环境下安装JDK
    Linux上安装tomcat
    Linux 下安装redis
    Map集合按照value和key进行排序
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15249725.html
Copyright © 2011-2022 走看看