zoukankan      html  css  js  c++  java
  • BZOJ5206 [Jsoi2017]原力[根号分治]

    这是一个三元环计数的裸题,只是多了一个颜色的区分和权值的计算罢了。

    有一种根号分治的做法(by gxz)

    这种复杂度的证明特别显然,思路非常简单,不过带一个log,可以用unordered_map或者bitset之类的$O(1)$判连通。


    我的做法的话采用了一个比较奇怪的思路?每条边,度数大的点向度数小的点连有向边,然后枚举第一层点,枚举出发到达的第二层点,这两层加起来复杂度总的是$O(m)$,然后从第二层点枚举出边到第三层点,看第三层点和第一层点是不是连通的,这个复杂度我好像在这里写过证明,就不贴了。注意一下重边的话,只要把相同颜色的权值累加起来做乘法就行(line47)。

    理论上说是根号的做法,但是我跑了9s???

    人家带一个log的都比我跑的快一倍,莫非我复杂度是假的?

    不清楚,如果有神仙指导不胜感激。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define mst(x) memset(x,0,sizeof x)
     8 #define dbg(x) cerr << #x << " = " << x <<endl
     9 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
    10 using namespace std;
    11 typedef long long ll;
    12 typedef double db;
    13 typedef pair<int,int> pii;
    14 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    15 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    16 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    17 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    18 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    19 template<typename T>inline T read(T&x){
    20     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;else if(c=='R'||c=='G'||c=='B'){x=c;break;}
    21     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    22 }
    23 const int N=1e5+7,P=1e9+7;
    24 struct thxorz{
    25     int head[N],w[N<<1],nxt[N<<1],to[N<<1],typ[N<<1],tot;
    26     thxorz(){tot=1;}
    27     inline void add(int x,int y,int z,int ty){to[++tot]=y,nxt[tot]=head[x],head[x]=tot,w[tot]=z,typ[tot]=ty;}
    28 }G,E;
    29 inline void add(int&a,int b){a+=b;a>=P&&(a-=P);}
    30 inline int mod(int a){return a>=P?a-=P:a;}
    31 int deg[N],vis[N][3],val[N][3];
    32 int n,m,ans;
    33 inline int cmp(int a,int b){return deg[a]==deg[b]?a<b:deg[a]<deg[b];}
    34 
    35 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    36     read(n),read(m);
    37     for(register int i=1;i<=m<<1;i+=2)++deg[read(E.to[i])],++deg[read(E.to[i+1])],read(E.w[i]),read(E.typ[i]);
    38     for(register int i=1;i<=m<<1;i+=2){
    39         if(!cmp(E.to[i],E.to[i+1]))G.add(E.to[i+1],E.to[i],E.w[i],E.typ[i]=='R'?0:(E.typ[i]=='G'?1:2));
    40         else G.add(E.to[i],E.to[i+1],E.w[i],E.typ[i]=='R'?0:(E.typ[i]=='G'?1:2));
    41     }
    42     for(register int x=1;x<=n;++x){//x
    43         #define y G.to[j]
    44         #define t G.typ[j]
    45         for(register int j=G.head[x];j;j=G.nxt[j]){
    46             if(vis[y][t]^x)vis[y][t]=x,val[y][t]=G.w[j];
    47             else add(val[y][t],G.w[j]);
    48         }
    49         #define z G.to[k]
    50         #define tt G.typ[k]
    51         for(register int j=G.head[x];j;j=G.nxt[j]){//y
    52             for(register int k=G.head[y];k;k=G.nxt[k])if(t^tt){//z
    53                 if(vis[z][3-t-tt]==x)add(ans,G.w[j]*1ll*G.w[k]%P*val[z][3-t-tt]%P);
    54             }
    55         }
    56     }
    57     printf("%d
    ",ans);
    58     return 0;
    59 }
    View Code

    总结:这相当于是把原来$O(mn)$的做法尝试通过连边、度数等减少枚举。。

  • 相关阅读:
    Visual Studio使用技巧
    排颜色问题——数组 leetcode lintcode
    【简洁】微信为何总令人感觉如此简洁、?(一)
    字符串通信协议解析函数
    我所改造的JSocket适用于任何DELPHI版本
    缓存和字符串相互转换
    TcxDBTreeList导出EXCEL
    TcxGrid导出EXCEL
    TdxAlertWindowManager右下角HINT显示控件
    好用的编辑框布局控件TdxLayoutControl
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11827619.html
Copyright © 2011-2022 走看看