# [2018HN省队集训D6T2] girls

## 题意

$$n,m\le 2\times 10^5$$.

## 题解

std::unordered_set 害人不浅...手写了一个十几行的Hash表判断联通性就过了...实测开 O2 之后查询时间要多 $$20$$ 倍.

### 参考代码

#include <bits/stdc++.h>

const int MOD=1e6+37;
const int MAXV=2e5+10;
const int MAXE=1e6+10;
typedef unsigned long long uintEx;

struct Edge{
int from;
int to;
Edge* next;
};
Edge E[MAXE];
Edge* top=E;

struct List{
uintEx key;
List* next;
List(const uintEx& k):key(k),next(NULL){}
};
List* L[MOD];

int v;
int e;
uintEx A;
uintEx B;
uintEx C;
int deg[MAXV];
std::vector<uintEx> le[MAXV];
std::vector<uintEx> gr[MAXV];

uintEx Sum(int,int);
void Insert(int,int);
bool Exist(const uintEx&);
void Insert(const uintEx&);

int main(){
for(int i=0;i<e;i++){
int a,b;
++a,++b;
Insert(a,b);
Insert(b,a);
++deg[a],++deg[b];
}
uintEx ans=0;
std::vector<int> large,small;
int sqre=sqrt(e);
for(int i=1;i<=v;i++){
ans+=(uintEx(i-1)*uintEx(i-2)/2)*C*uintEx(i-1);
ans+=uintEx(i-1)*uintEx(v-i)*B*uintEx(i-1);
ans+=(uintEx(v-i)*uintEx(v-i-1)/2)*A*uintEx(i-1);
std::sort(le[i].begin(),le[i].end());
std::sort(gr[i].begin(),gr[i].end());
for(size_t k=1;k<le[i].size();k++)
le[i][k]+=le[i][k-1];
for(size_t k=1;k<gr[i].size();k++)
gr[i][k]+=gr[i][k-1];
if(deg[i]>sqre)
large.push_back(i);
else
small.push_back(i);
}
for(Edge* i=E;i!=top;i++){
if(i->from<i->to){
ans-=Sum(0,i->from-2)*A+uintEx(i->from-1)*(B*(i->from-1)+C*(i->to-1));
ans-=Sum(i->from,i->to-2)*B+uintEx(i->to-i->from-1)*(A*(i->from-1)+C*(i->to-1));
ans-=Sum(i->to,v-1)*C+uintEx(v-i->to)*(A*(i->from-1)+B*(i->to-1));
}
}
for(int i=1;i<=v;i++){
if(!le[i].empty()&&!gr[i].empty())
ans+=(*le[i].rbegin())*uintEx(gr[i].size())*A
+uintEx(le[i].size())*uintEx(gr[i].size())*B*(i-1)
+(*gr[i].rbegin())*uintEx(le[i].size())*C;
for(size_t k=1;k<le[i].size();k++)
ans+=le[i][k-1]*A+((le[i][k]-le[i][k-1])*B+(i-1)*C)*k;
for(size_t k=1;k<gr[i].size();k++)
ans+=gr[i][k-1]*B+((gr[i][k]-gr[i][k-1])*C+(i-1)*A)*k;
}
uintEx triple=0;
std::sort(large.begin(),large.end());
for(size_t ii=0;ii<large.size();ii++){
int i=large[ii];
for(size_t jj=ii+1;jj<large.size();jj++){
int j=large[jj];
if(!Exist((uintEx(i)<<32)|j))
continue;
for(size_t kk=jj+1;kk<large.size();kk++){
int k=large[kk];
if(Exist((uintEx(i)<<32)|k)&&Exist((uintEx(j)<<32)|k))
triple+=(i-1)*A+(j-1)*B+(k-1)*C;
}
}
}
int cnt=0;
for(auto s:small){
if(deg[i->to]<=sqre&&i->to<=s)
continue;
for(Edge* j=i->next;j!=NULL;j=j->next){
if(deg[j->to]<=sqre&&j->to<=s)
continue;
assert(++cnt<=2e7);
if(Exist((uintEx(i->to)<<32)|j->to)){
uintEx q[3]={s-1,i->to-1,j->to-1};
std::sort(q,q+3);
triple+=q[0]*A+q[1]*B+q[2]*C;
}
}
}
}
ans-=triple;
printf("%llu\n",ans);
return 0;
}

inline uintEx Sum(int l,int r){
return l<=r?uintEx(l+r)*uintEx(r-l+1)/2:0;
}

inline void Insert(int from,int to){
Insert((uintEx(from)<<32)|to);
if(to>from)
gr[from].push_back(to-1);
else
le[from].push_back(to-1);
top->from=from;
top->to=to;
}

target=0;
register char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch)){
target=target*10+ch-'0';
ch=getchar();
}
}

template<typename Int,typename... Arg> void ReadInt(Int& target,Arg&... args){
}

inline void Insert(const uintEx& k){
int pos=k%MOD;
if(!L[pos])
L[pos]=new List(k);
else{
List* cur=L[pos];
while(cur->next&&cur->key!=k)
cur=cur->next;
if(cur->key!=k)
cur->next=new List(k);
}
}

inline bool Exist(const uintEx& k){
for(List* cur=L[k%MOD];cur!=NULL;cur=cur->next){
if(cur->key==k)
return true;
}
return false;
}



posted @ 2019-03-07 16:32  rvalue  阅读(310)  评论(2编辑  收藏  举报