bzoj3498: PA2009 Cakes

Description

N个点m条边,每个点有一个点权a。
对于任意一个三元环(j,j,k)(i<j<k),它的贡献
为max(ai,aj,ak) 
求所有三元环的贡献和。
N<100000,,m<250000。

对度数大的点w,枚举w相邻的每个点u1,u2,u3...,遍历u[a]相邻的点的统计w,u[a],u[b](b<a)构成三元环的情况

对度数小的点w,枚举w相邻的每个点,在另外存边的散列表中 判断它们两两之间是否有边

每个三元环恰好统计三次,两种策略时间复杂度在判断标准为$\sqrt{m}$时达到平衡

#include<cstdio>
#include<vector>
const int RN=1e5;
char buf[RN+7],*ptr=buf+RN;
int G(){
    if(ptr==buf+RN)fread(ptr=buf,1,RN,stdin);
    return *ptr++;
}
int _(){
    int x=0;
    if(ptr<buf+RN-50){
        while(*ptr<48)++ptr;
        while(*ptr>47)x=x*10+*ptr++-48;
    }else{
        int c=G();
        while(c<48)c=G();
        while(c>47)x=x*10+c-48,c=G();
    }
    return x;
}
const int P=1844677,N=1e5+7,D=333;
int n,m,a[N],ed[N],e[N*3][2],deg[N],*lr[N][2],mem[N*5],*mp=mem;
int max(int a,int b){return a>b?a:b;}
long long ans=0;
int h[P][2];
void ins(int a,int b){
    int w=(a*1399+b*2939)%P;
    while(h[w][0]){
        if(h[w][0]==a&&h[w][1]==b)return;
        w=(w+21331)%P;
    }
    h[w][0]=a,h[w][1]=b;
}
bool find(int a,int b){
    int w=(a*1399+b*2939)%P;
    while(h[w][0]){
        if(h[w][0]==a&&h[w][1]==b)return 1;
        w=(w+21331)%P;
    }
    return 0;
}
int main(){
    n=_(),m=_();
    for(int i=1;i<=n;++i)a[i]=_();
    for(int i=1;i<=m;++i){
        ++deg[e[i][0]=_()];
        ++deg[e[i][1]=_()];
    }
    for(int i=1;i<=n;++i)lr[i][0]=lr[i][1]=mp,mp+=deg[i];
    for(int i=1;i<=m;++i){
        int a=e[i][0],b=e[i][1];
        *lr[a][1]++=b;
        *lr[b][1]++=a;
        ins(a,b);
        ins(b,a);
    }
    for(int i=1;i<=n;++i)if(deg[i]>D){
        for(int*j=lr[i][0];j!=lr[i][1];++j){
            int w=*j,mx=max(a[i],a[w]);
            ed[w]=i;
            for(int*k=lr[w][0];k!=lr[w][1];++k)if(ed[*k]==i)ans+=max(mx,a[*k]);
        }
    }else{
        for(int*j=lr[i][0];j!=lr[i][1];++j){
            int w=*j,mx=max(a[i],a[w]);
            for(int*k=lr[i][0];k!=j;++k)if(find(w,*k))ans+=max(mx,a[*k]);
        }
    }
    printf("%lld\n",ans/3);
    return 0;
}
时间: 2024-08-29 05:46:38

bzoj3498: PA2009 Cakes的相关文章

BZOJ 3498: PA2009 Cakes

Description \(n\)个点\(m\)条边,求所有三元环,一个三元环的贡献为三个点中权值最大的点.\(n\leqslant 1\times 10^5,n\leqslant 2.5\times 10^5\) Solution 分类讨论. 只从权值大的点连向权值小的点,因为可能权值相同,顺序需要确定下来. 枚举所有边. 如果一个点的度数小于等于\(\sqrt m\)那么枚举所有的点,看看他和另一个点有没有连边,直接用map存一下... 如果度数大于\(\sqrt m\)那么枚举另一个点的所

省选之前的未完成的计划(截至到省选)

PLAN OF THE COMING HEOI good problems:-bzoj4823:[Cqoi2017]老C的方块 [*]-bzoj3171:[Tjoi2013]循环格 [*]-bzoj4200:[Noi2015]小园丁与老司机 [*]-bzoj1061:[Noi2008]志愿者招募 [*]-bzoj3600:没有人的算术 [*]-bzoj2806:[Ctsc2012]Cheat [*]-bzoj2219:数论之神 [*]-bzoj2595:[Wc2008]游览计划 [*]-bzoj

波兰题目补全计划

Introduce 本人比较喜欢做波兰的题目,感觉这些题目十分清真,思维也比较好.欢迎同样喜欢波兰题目的OIer来交流.以下是我有记录地刷过的题目. 比较好的题吧:BZOJ #3746.[POI2015]Czarnoksi??nicy okr?g?ego sto?u source:XXII OI - Etap I - Zadanie Czarnoksi??nicy okr?g?ego sto?u notes: 动态规划我的题解http://www.cnblogs.com/TSHugh/p/882

hdu 5997 rausen loves cakes(线段数合并+启发式修改)

题目链接:hdu 5997 rausen loves cakes 题意: 给你n个点,每个点有一个颜色,现在有两个操作,第一个操作,将颜色x改为颜色y,第二个操作,询问[x,y]区间有多少颜色段(颜色段的定义为从左往右相同的颜色为一段,遇到不相同的为下一段,ie:144112为4段颜色) 题解: 对于第二个操作我们可以写一个线段树合并来搞定,对于第一个操作,就要用启发式修改来进行,如何启发式? 我们开一个数组来记录每个颜色对应的颜色,最开始都是对应自己,然后开一个vector来记录每个颜色的位置

BZOJ3072 : [Pa2012]Two Cakes

考虑DP,设$f[i][j]$表示考虑了$a[1..i]$和$b[1..j]$的最小代价. 若$a[i]==b[j]$,则$f[i][j]=\min(f[i-1][j],f[i][j-1])+1$. 否则找到最大的$t$,满足$x$和$y$往前$t$个均不相等,此时$f[i][j]=f[i-t-1][j-t-1]+t$. 对于$t$,可以通过在相应差值的序列中二分查找得到. 对于DP的计算,可以通过搜索,并将那$n$个$a[i]==b[j]$的状态记忆化. 因为对于每个没有记忆化的状态,均可以在

bzoj4232: [Neerc2011 Northern]Kids Like Cakes

Description 给定一个n个点的严格凸多边形(各个内角<180°),现在要切出两个非退化三角形(三点不共线),要求两个三角形顶点必须是凸多边形的顶点,且三角形不可相交(但是点或边可以重合).求两个三角形面积之差的最大值. Input 第一行,一个整数N. 第二到N+1行,每行两个整数xi,yi,表示多边形的一个点,保证顶点按顺时针或逆时针顺序给出. Output 输出答案,精确到小数点后1位. 最小三角形一定是相邻三点构成,因此只需枚举每个最小三角形,查询剩余部分中的最大三角形 dp,f

【BZOJ3072】[Pa2012]Two Cakes【DP】

[题目链接] 题解: 很容易想到O(n^2)DP的做法. (1)A[i] == B[j],dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1 (2)A[i] != B[j],dp[i][j] = dp[i - t + 1][j - t + 1] + t,t表示最长的一段不相等的数的长度 发现如果连续的一段内要填写的两个数都不相同,那么一定是贪心转移的,即只有数字相同的地方需要DP. 如何快速找到t? 考虑全排列每个数字只出现了一次,可以得出相同数字的位置

【Educational Codeforces Round 35 C】Two Cakes

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 直觉题. 感觉情况会很少. 毕竟间隔太大了.中间肯定有一些数字达不到. 有1肯定可以 2 2 x肯定可以 3 3 3也可以 2 4 4也可以. 就这样 [代码] #include <bits/stdc++.h> using namespace std; vector <int> v; int main(){ #ifdef LOCAL_DEFINE freopen("rush_in.txt", &

B.Two Cakes

链接:https://codeforces.com/contest/1130/problem/B 题意: 给定n和 2 * n个数,表示i位置卖ai层蛋糕, 有两个人在1号,必须严格按照1-n的顺序买蛋糕,同时每个店只买一个蛋糕 . 求所需的最短时间. 思路: 将每种蛋糕对应位置记录在二维数组. 从1-n挨个买,根据上一次的位置算出消耗. 代码: #include <bits/stdc++.h> using namespace std; typedef long long LL; const