Codeforces 题目传送门 & 洛谷题目传送门

真·ycx 做啥题我就做啥题

考虑枚举 \(j\),我们预处理出 \(c1_i\) 表示与 \(i\) 相连的编号 \(<i\) 的点的个数,再预处理出 \(c2_i\) 表示与 \(i\) 相连的编号 \(>i\) 的个数,那么共有 \(j-c1_j\) 个 \(<j\) 的数可以成为 \(i\),有 \(n-1-c2_j\) 个数可以成为 \(k\),贡献就随便算一下就行了。

但是这样会多算,多算的部分就是 \(i,k\) 有边相连,但 \((i,j),(k,j)\) 均无边相连的部分。考虑另外减去这一部分的贡献,这一次我们枚举有边相连的 \((i,k)\)——显然这一部分复杂度是 \(\mathcal O(m)\) 的,并且钦定 \(i<k\),那么显然对于所有多算的 \(j\),必然有 \((i,j),(k,j)\) 均无边,我们记这样符合要求的 \(j\) 有 \(c\) 个,它们的和为 \(s\),那么多算的贡献就是 \(cAi+cCk+sB\),减一下就行了。

不过到这里有一个问题,那就是符合条件的 \(j\) 无法直接计算,因为这里的 \((i,k)\) 不独立,要是能拆开来计算就好了,可这里拆不掉。考虑有个东西叫做正难则反,我们考虑拿所有符合要求的 \(j\) 减去 \((i,j),(k,j)\) 至少一个有边的 \(j\) 即可。不过到这里问题又来了,那就是这东西还是不好维护,继续考虑容斥原理,这东西又等价于 \((i,j)\) 有边的 \(j\) \(+\) \((k,j)\) 有边的 \(j\),扣掉 \((i,j),(k,j)\) 都有边的 \(j\),而前面这两个东西恰好是可以分开来算的,相当于我们要分别求对于固定的 \(i,k\),满足 \((i,j)\) 之间存在边,并且 \(i<j<k\) 的 \(j\) 的个数及和;以及 \((k,j)\) 之间存在边,并且 \(i<j<k\) 的 \(j\) 的个数及和——拿前一部分举例,我们对于每个 \(i\) 建一个 std::vector<int> \(g2_i\),维护所有 \(j>i,(i,j)\) 之间有边的 \(j\) 并将其排个序,再建另一个 std::vector<int> \(s2_i\) 维护 \(g2_i\) 的前缀和,然后在 \(g2_i\) 中 std::lower_bound 找出 \(k\) 的位置,查遍前缀和即可。

最后考虑 \((i,j),(k,j),(i,k)\) 都有边的 \(i,j,k\) 的贡献,这是一个非常经典的问题,叫「三元环计数」。然鹅 wtcl 在做这题之前还不会这个科技,所以感谢这个题让我学会了这玩意儿。考虑对原图中每条边重新定向,对于无向边 \((u,v)\),只从度数小的连向度数大的边,如果度数相同比编号,显然这样形成一个偏序集,于是每一个三元环 \((i,j,k)\) 与每一个满足 \(i\to j,j\to k,i\to k\) 的边都存在的三元组 \((i,j,k)\) 形成双射,我们就非常暴力地枚举 \(i\),再枚举它的出边 \(j\),再枚举它的出边 \(k\),并检验 \(i\to k\) 的边是否存在即可。容易证明这样复杂度是 \(m\sqrt m\) 的。

总之这题就是一堆正难则反,思维难度倒不算太大

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e5;
int n,m,deg[MAXN+5];u64 a,b,c;
u64 sum(u64 l,u64 r){return (l+r)*(r-l+1)/2ull;}
vector<int> g1[MAXN+5],g2[MAXN+5],g[MAXN+5];
vector<u64> s1[MAXN+5],s2[MAXN+5];
int vis[MAXN+5];
int main(){
scanf("%d%d%llu%llu%llu",&n,&m,&a,&b,&c);
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);if(u>v) u^=v^=u^=v;
g1[v].pb(u);g2[u].pb(v);deg[u]++;deg[v]++;
}
u64 ans=0;
for(int i=0;i<n;i++){
sort(g1[i].begin(),g1[i].end());
s1[i].resize(g1[i].size());
for(int j=0;j<g1[i].size();j++){
if(j==0) s1[i][j]=g1[i][j];
else s1[i][j]=s1[i][j-1]+g1[i][j];
}
sort(g2[i].begin(),g2[i].end());
s2[i].resize(g2[i].size());
for(int j=0;j<g2[i].size();j++){
if(j==0) s2[i][j]=g2[i][j];
else s2[i][j]=s2[i][j-1]+g2[i][j];
}
}
for(int i=0;i<n;i++){
u64 cnt1=i-g1[i].size(),cnt2=n-i-1-g2[i].size();
u64 sum1=sum(0,i-1)-((g1[i].empty())?0:s1[i].back());
u64 sum2=sum(i+1,n-1)-((g2[i].empty())?0:s2[i].back());
ans+=cnt1*cnt2*i*b+cnt1*sum2*c+cnt2*sum1*a;
}
for(int i=0;i<n;i++) for(int j:g2[i]){
int pos1=lower_bound(g1[j].begin(),g1[j].end(),i)-g1[j].begin();
int pos2=lower_bound(g2[i].begin(),g2[i].end(),j)-g2[i].begin();
u64 cnt=g1[j].size()-1-pos1+pos2;
u64 rem=j-i-1-cnt;
u64 s=sum(i+1,j-1)-s1[j].back()+s1[j][pos1]-((!pos2)?0:s2[i][pos2-1]);
// printf("%d %d %d %d\n",i,j,rem,s);
ans-=s*b+rem*i*a+rem*j*c;
}
for(int i=0;i<n;i++) for(int j=0;j<g1[i].size();j++){
int x=g1[i][j];
if(deg[i]<deg[x]) g[i].pb(x);
else g[x].pb(i);
} memset(vis,-1,sizeof(vis));
for(int i=0;i<n;i++){
for(int j:g[i]) vis[j]=i;
for(int j:g[i]) for(int k:g[j]){
if(vis[k]==i){
// printf("%d %d %d\n",i,j,k);
u64 tmp[3]={0};tmp[0]=i;tmp[1]=j;tmp[2]=k;
sort(tmp,tmp+3);ans-=tmp[0]*a+tmp[1]*b+tmp[2]*c;
}
}
}
printf("%llu\n",ans);
return 0;
}

Codeforces 985G - Team Players(三元环)的更多相关文章

  1. Codeforces 985G. Team Players

    Description 有 \(n\) 个人 , \(m\) 对人有冲突 , 你要从这 \(n\) 个人中选出三个人成为一组 , 使得同一组的人不存在一对有冲突 题面 Solution 容斥 答案=总 ...

  2. BZOJ.5407.girls/CF985G. Team Players(三元环计数+容斥)

    题面 传送门(bzoj) 传送门(CF) \(llx\)身边妹子成群,这天他需要从\(n\)个妹子中挑出\(3\)个出去浪,但是妹子之间会有冲突,表现为\(i,j\)之间连有一条边\((i,j)\), ...

  3. Codeforces Gym 100342J Problem J. Triatrip 求三元环的数量 bitset

    Problem J. Triatrip Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100342/at ...

  4. Codeforces Gym 100342J Problem J. Triatrip 三元环

    题目链接: http://codeforces.com/gym/100342 题意: 求三元环的个数 题解: 用bitset分别统计每个点的出度的边和入度的边. 枚举每一条边(a,b),计算以b为出度 ...

  5. Codeforces Gym 100342J Problem J. Triatrip bitset 求三元环的数量

    Problem J. TriatripTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100342/att ...

  6. Codeforces 434E - Furukawa Nagisa's Tree(三元环+点分治)

    Codeforces 题面传送门 & 洛谷题面传送门 场号 hopping,刚好是我的学号(指 round 的编号) 注:下文中分别用 \(X,Y,K\) 代替题目中的 \(x,y,k\) 注 ...

  7. BZOJ.5407.girls(容斥 三元环)

    题目链接 CF 原题 \(Description\) 有n个点,其中有m条边连接两个点.每一个没有连边的三元组\((i,j,k)(i<j<k)\)对答案的贡献为\(A*i+B*j+C*k\ ...

  8. BZOJ 3498 PA2009 Cakes(三元环处理)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3498 [题目大意] N个点m条边,每个点有一个点权a. 对于任意一个三元环(j,j,k ...

  9. HDU 6184 Counting Stars 经典三元环计数

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6184 题意: n个点m条边的无向图,问有多少个A-structure 其中A-structure满足V ...

随机推荐

  1. 用例图示例:使用系统边界表示多个项目 / Using System Boundary to model Multiple Projects in Use Case Diagram

    什么是用例图? 用例是一种捕获系统功能需求的技术.用例描述了一个独立于实现细节的期望行为.用例的目标是捕获用户设想的所有系统级功能.从用户的角度来看,用例是关于系统应该做什么的.用例捕获系统利益相关者 ...

  2. MySQL:基础语法-1

    MySQL:基础语法-1 记录一下 MySQL 基础的一些语法,便于查询,该部分内容主要是参考:bilibili 上 黑马程序员 的课程而做的笔记,由于时间有点久了,课程地址忘记了 关于数据库的安装操 ...

  3. 实用小工具:screen

    实用小工具:screen 首先,吹爆screen screen,实现了不间断的会话服务,通过SSH连接至远程服务器,当使用了screen开启的会话,不会因为你断开SSH而中断在远程服务器上运行的命令. ...

  4. 《Spring源码深度解析》学习笔记——Spring的整体架构与容器的基本实现

    pring框架是一个分层架构,它包含一系列的功能要素,并被分为大约20个模块,如下图所示 这些模块被总结为以下几个部分: Core Container Core Container(核心容器)包含有C ...

  5. 异常大讨论-抛出异常还是返回false

    iteye精华帖之异常大讨论 原帖链接http://www.iteye.com/topic/2038 Robbin的观点 观点1:Exception实际上代表了一个UseCase中的异常流的处理. 绝 ...

  6. [对对子队]会议记录5.20(Scrum Meeting7)

    今天已完成的工作 马嘉 ​ 工作内容:录制新手引导视频 ​ 相关issue:优化顺序关卡新手引导功能 ​ 相关签入:feat: 录制了新的新手引导视频 吴昭邦 ​ 工作内容:增加加速功能 ​ 相关is ...

  7. spring cloud feign的基本使用

    在上一节,我们学会了如何使用ribbon进行来进行服务之间的调用,但是那种需要通过RestTemplate来进行调用而且当参数比较多时,使用起来就比较麻烦.那么有没有一种调用远程方法(别的服务)就像调 ...

  8. 21.10.14 test

    题目 WOJ5078 到 WOJ5081 T1 Problem A \(\color{green}{100}\) 由于每轮要选择尽量多的边删除,所以想到无向图的生成树,因为在生成树上再加一条边就会形成 ...

  9. python fnmatch & glob

    1,转载:Python模块学习 - fnmatch & glob - Dahlhin - 博客园 (cnblogs.com) 介绍 fnmatch 和 glob 模块都是用来做字符串匹配文件名 ...

  10. 第K个数 牛客网 程序员面试金典 C++ Python

    第K个数 牛客网 程序员面试金典 C++ Python 题目描述 有一些数的素因子只有3.5.7,请设计一个算法,找出其中的第k个数. 给定一个数int k,请返回第k个数.保证k小于等于100. 测 ...