Codeforces Round #614 选讲

http://codeforces.com/contest/1292/problem/C

注意到编号x的边对答案要有贡献,必须和0到x-1的边一起形成一条链,否则x及编号比x大的边都没有贡献。由此,对答案有贡献的边形成了一条链,且这条链的编号是个谷形,即中间编号小,往两边编号变大,编号最大的边在最外侧。由此可以进行dp,dp[u][v]表示如果上述链为点u到点v这条链的答案。令sz[u][v]为以u为根,子树v的大小;fa[u][v]为以u为根,点v的父亲,则有dp[u][v]=dp[v][u]=sz[u][v]*sz[v][u]+max(dp[u][fa[u][v]],dp[v][fa[v][u]])。(考虑放入编号最大的一条边,相当于某些路径的mex增加了1)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4
 5 int n;
 6 #define maxn 3011
 7 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
 8 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
 9 void insert(int x,int y) {in(x,y); in(y,x);}
10
11 int sz[maxn][maxn],fa[maxn][maxn];
12 LL dp[maxn][maxn];
13 struct NODE{int x,y;};
14 vector<NODE> vec[maxn];
15 void dfs(int x,int f,int top,int dep)
16 {
17     sz[top][x]=1; fa[top][x]=f;
18     if (dep>0) vec[dep].push_back((NODE){top,x});
19     for (int i=first[x];i;i=edge[i].next)
20     {
21         Edge &e=edge[i]; if (e.to==f) continue;
22         dfs(e.to,x,top,dep+1); sz[top][x]+=sz[top][e.to];
23     }
24 }
25
26 int main()
27 {
28     scanf("%d",&n);
29     for (int i=1,x,y;i<n;i++) {scanf("%d%d",&x,&y); insert(x,y);}
30     for (int i=1;i<=n;i++) dfs(i,0,i,0);
31
32     for (int len=1;len<n;len++)
33         for (int i=0,to=vec[len].size();i<to;i++)
34         {
35             int a=vec[len][i].x,b=vec[len][i].y;
36             dp[a][b]=dp[b][a]=sz[a][b]*sz[b][a]+max(dp[a][fa[a][b]],dp[b][fa[b][a]]);
37         }
38
39     LL ans=0;
40     for (int i=1;i<=n;i++)
41         for (int j=1;j<=n;j++)
42             ans=max(ans,dp[i][j]);
43     printf("%lld\n",ans);
44     return 0;
45 }

http://codeforces.com/contest/1292/problem/D

回忆找重心的过程:从根节点开始,看点权和最大的子树,其点权和是否超过总的一半,是则在该子树中找重心,否则当前点为重心。以1为根时,在深度dep的节点x的子树中的点y必须满足:y的质因子中最大的dep个乘积即为x。由此,从1出发,对所有数进行分解后(相同的合并),每次取每个数的最大的质因子p,算出每个p的点权和,然后看重儿子的点权和是否超过n/2,若否则找到答案,若是则调整答案,并删去该子树中的最大质因子(将其次数-1),然后在该子树中循环进行该过程。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4
 5 int n;
 6 #define maxn 5011
 7 #define MAXNUM 5000
 8 int cnt[maxn],fra[maxn][maxn],poi[maxn],cntpri[maxn],pri[maxn],lp; bool vis[maxn];
 9 void makeprime(int n)
10 {
11     for (int i=2;i<=n;i++)
12     {
13         if (!vis[i]) pri[++lp]=i;
14         for (int j=1;j<=lp && 1ll*i*pri[j]<=n;j++)
15         {
16             vis[i*pri[j]]=1;
17             if (i%pri[j]==0) break;
18         }
19     }
20 }
21
22 int main()
23 {
24     scanf("%d",&n);
25     for (int i=1,x;i<=n;i++) scanf("%d",&x),cnt[x]++;
26     makeprime(MAXNUM);
27
28     LL ans=0;
29     for (int x=0;x<=MAXNUM;x++)
30         for (int i=1;i<=lp && pri[i]<=x;i++)
31         {
32             for (int j=pri[i];j<=x;j*=pri[i])
33                 fra[x][i]+=x/j;
34             ans+=1ll*cnt[x]*fra[x][i];
35         }
36         //trick: The number of prime 2 in k! is k/2+k/4+k/8+...
37
38     for (int x=0;x<=MAXNUM;x++) poi[x]=lp;
39     while (1)
40     {
41         for (int i=1;i<=lp;i++) cntpri[i]=0;
42         for (int x=0;x<=MAXNUM;x++)
43         {
44             while (poi[x]>0 && fra[x][poi[x]]==0) poi[x]--;
45             if (poi[x]>0) cntpri[poi[x]]+=cnt[x];
46         }
47         bool findans=1;
48         for (int i=1;i<=lp;i++) if (cntpri[i]*2>n)
49         {
50             findans=0;
51             ans-=cntpri[i]-(n-cntpri[i]);
52             for (int x=0;x<=MAXNUM;x++) if (poi[x]>0 && poi[x]==i) fra[x][poi[x]]--; else poi[x]=0;
53             break;
54         }
55         if (findans) break;
56     }
57     printf("%lld\n",ans);
58     return 0;
59 }

原文地址:https://www.cnblogs.com/Blue233333/p/12239920.html

时间: 2024-08-30 09:26:29

Codeforces Round #614 选讲的相关文章

Codeforces Round #614 (Div. 2) E. Xenon&#39;s Attack on the Gangs

On another floor of the A.R.C. Markland-N, the young man Simon "Xenon" Jackson, takes a break after finishing his project early (as always). Having a lot of free time, he decides to put on his legendary hacker "X" instinct and fight ag

Codeforces Round #614 (Div. 2) D. Aroma&#39;s Search

题目链接:http://codeforces.com/contest/1293/problem/D 题意: 给定x0,y0,ax,ay,bx,by 即一堆经验点:(x0,y0),(x1,y1)等价于(ax*x0+bx,ay*y0+by),(x2,y2)等价于(ax*x1+bx,ay*y1+by),(x3,y3)等价于(ax*x2+bx,ay*y2+by)...... 再给定xs,ys,t 即起点(xs,ys),时间t 上下左右每走一步都需要1单位时间,问在t时间内,从起点出发最多可以吃到多少个经

Codeforces Round #614 (Div. 2) C. NEKO&#39;s Maze Game

题目链接:http://codeforces.com/contest/1293/problem/C 题意:给定n,q,即给定一个2*n的格子,有q个查询. 每个查询给定一个ri和ci,ri为1或2,ci在1到n之间,即给定一个(ri,ci),该点自该查询起状态进行转变(可经过/不可经过). 如某个查询给定1,2,即点(1,2)无法经过,若之后查询再次给定1,2,则该点(1,2)可以经过. 问能否从(1,1)走到(2,n),保证给定的查询不会经过起点和终点. 思路: 由于n和q最大都是1e5,所以

Codeforces Round #614 (Div. 2)

A. ConneR and the A.R.C. Markland-N 题目链接:https://codeforces.com/contest/1293/problem/A 题意: 有一个长为 n 的楼层,其中有 k 个楼层没有餐厅 ,你现在在 s 层,问你最少走多少个楼层可以到达餐厅吃饭 分析: 因为 k 只有 1000,所以直接往 s 层上下方找(当找到 0 或者 n + 1 时说明这个方向没有答案) #include<bits/stdc++.h> using namespace std;

Codeforces Round #614 (Div. 2) 比赛总结

比赛情况 怒切 \(A,B,C,D\),后面 \(E,F\) 两题技术太菜不会做,不知道什么时候可以补起来. 比赛总结 事实证明: 比赛前喝一瓶抗疲劳饮料对比赛状态的进入有显著效果. 比赛有人陪着打对AC题目有显著效果. 说正经的: 不要紧张,也不要太过放松.这样才有利于发挥出真实水平. 下面就开始 喜闻乐见 的题解吧. A 入门题 枚举找到最近的可用楼层即可.用 \(STL\) 里面的 map 判断一个楼层是否可用使用. Code #include<bits/stdc++.h> #defin

Codeforces Round #614 (Div. 2) B - JOE is on TV!

原题题面:https://codeforces.com/contest/1293/problem/B 解题思路: Σi=1~n 1/i ??? 1 /* 2 Written By. StelaYuri 3 On 2020/01/19 4 */ 5 #include<bits/stdc++.h> 6 using namespace std; 7 typedef long long ll; 8 int a[1005],b[1005]; 9 void solve(){ 10 int n,i; 11

Codeforces Round #614 (Div. 2) A - ConneR and the A.R.C. Markland-N

原题题面:https://codeforces.com/contest/1293/problem/A 题目大意: ConneR老师想吃东西,他现在在大楼的第s层,大楼总共有n层,但是其中有k层的餐厅关门了. 然后给了这k层关门的餐厅分别所在的楼层. 所以问ConneR老师最少得往上(或者往下)走几层楼,才能到最近的还开门的餐厅就餐? 解题思路1: 对于关闭的k层,存在数组a里排序.(放在1~k的位置) 先循环一遍数组a,看看s层是否存在于a数组里,如果不存在,直接输出0作为答案. 如果存在,开始

Codeforces Round #614 (Div. 2) A( A - ConneR and the A.R.C. Markland-N)

A - ConneR and the A.R.C. Markland-N 题目链接:http://codeforces.com/contest/1293/problem/A 题意:一栋楼房有n(1~n)层,有个人身处s楼,现在想要到餐厅吃饭,可是现在有k个餐厅关闭的,问你该人至少爬几层楼梯才能到开放的餐厅吃饭 思路:...这题暴力没戏..又是超时又是超内存...分两种,一个是往上找出最小的i-s即可,一个是往下找,找出最小的s-i即可,,用了数组还是超时..用了map就过了 // // Crea

Codeforces Hello 2020 选讲

http://codeforces.com/contest/1284/problem/D 把区间对的第二维放入以第一维为下标的数轴中(如1 2 3 4,就把区间[3,4]放入位置1和位置2),如此同个位置的所有区间必须两两相交,即检验第一维相交?第二维相交.同理检验第二维相交?第一维相交.“放入”可用差分的方式.检验:新加入一个区间[x,y],必须满足y>=s_max,且x<=e_min,其中s和e是起点和终点.可用multiset维护加入.检测.删除. 1 #include <bits