CF#384 (Div.2) 解题报告
来源:互联网 发布:linux下解压rar文件 编辑:程序博客网 时间:2024/05/17 04:54
A
题意
有2家公司,相同公司互相传送花费为0,不同公司花费为坐标之差的绝对值。给出公司分布,问从a到b的花费最少是多少。
题解
如果ab公司相同,那么费用为0
否则的话费用为1
正确性显然
B
题意
起始数字为1,然后经过如下变换:
1
121
1213121
121312141213121
…
问第n-1次变换后第k个位置的数是多少
题解
可以发现这个数列满足二分的性质,那么从直接从n开始二分并且每一次都-1就可以了。
这道题的规律非常多啊。。。
注意:爆int
C
题意
给出n,求使
题解
“裂(三声)项相消法”。。
D
题意
一棵树,每个点有一个权,从中选两个互不包含的子树使子树的和最大。
题解
树形dp啊显然。。。
求出来子树的和了之后维护一个最大值和次大值就可以了。
坑点:刚开始的时候Impossible判错了,应该是-inf的问题。这种的点一定要谨慎。
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define LL long long #define N 200005const LL inf=1e18;int n,x,y;LL st,val[N],size[N],f[N][3];int tot,point[N],nxt[N*2],v[N*2];void add(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void dfs(int x,int fa){ size[x]=val[x]; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) { dfs(v[i],x); size[x]+=size[v[i]]; }}void treedp(int x,int fa){ f[x][1]=size[x]; LL Max=-inf,_Max=-inf; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) { treedp(v[i],x); f[x][1]=max(f[x][1],f[v[i]][1]); f[x][2]=max(f[x][2],f[v[i]][2]); if (f[v[i]][1]>=Max) _Max=Max,Max=f[v[i]][1]; else _Max=max(_Max,f[v[i]][1]); } if (Max!=-inf&&_Max!=-inf) f[x][2]=max(f[x][2],Max+_Max);}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%I64d",&val[i]); for (int i=1;i<n;++i) { scanf("%d%d",&x,&y); add(x,y);add(y,x); } dfs(1,0); memset(f,128,sizeof(f)); treedp(1,0); if (f[1][2]<=-inf) puts("Impossible"); else printf("%I64d\n",f[1][2]);}
E
题意
给出一个只有1-8的数列,求一个最长的子序列,满足这个子序列里1-8这8个数任意两数的出现次数之差的绝对值都
题解
二分+dp。
可以发现如果1-8没有在数列里全部出现的话,那么出现的数只可以每一种选一个。这一条特判。
如果都出现过的话,每一个数的出现次数只可能有2种,并且这两个次数相差1。那么我们可以二分每一个数的出现次数中较小的那个数,然后在判断是否可行。
需要用-1和-inf来判断各种状态是否合法。
刚开始犯了一个错误,就是判断是否合法的时候。界限应该宽松一些,否则轻微的调整都有可能出错。
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define N 1005int n,tot,ans,Max,inf;int a[N],g[N][N][2],f[1<<9][N];bool flag[10];bool check(int mid){ memset(g,-1,sizeof(g));memset(f,128,sizeof(f));inf=f[0][0]; for (int i=1;i<=8;++i) { for (int j=1,cnt=0;j<=n;++j,cnt=0) for (int k=j;k<=n;++k) { if (a[k]!=i) continue; cnt++; if (cnt==mid) g[j][i][0]=k; if (cnt==mid+1) {g[j][i][1]=k;break;} } } f[0][1]=0; for (int i=0;i<1<<8;++i) for (int j=1;j<=n;++j) { for (int k=1;k<=8;++k) { if ((i>>(k-1))&1) continue; if (g[j][k][0]!=-1) f[i|(1<<(k-1))][g[j][k][0]+1]=max(f[i|(1<<(k-1))][g[j][k][0]+1],f[i][j]+mid); if (g[j][k][1]!=-1) f[i|(1<<(k-1))][g[j][k][1]+1]=max(f[i|(1<<(k-1))][g[j][k][1]+1],f[i][j]+mid+1); } } ans=inf; for (int i=1;i<=n+1;++i) ans=max(ans,f[(1<<8)-1][i]); if (ans<=0) return false; else return true;}int find(){ int l=0,r=n/8+1,mid; while (l<=r) { mid=(l+r)>>1; if (check(mid)) { Max=max(Max,ans); l=mid+1; } else r=mid-1; }}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d",&a[i]),flag[a[i]]=true; for (int i=1;i<=8;++i) tot+=flag[i]; if (tot<8) {printf("%d\n",tot);return 0;} find(); printf("%d\n",Max); return 0;}
总结
遇到奇怪的问题不要着急,特判要想清楚,尤其是-inf之类的东西。
数学题不要慌,好好搞一搞。
- CF#384 (Div.2) 解题报告
- CF#386(Div.2) 解题报告
- CF#398(Div.2) 解题报告
- CF#401(Div.2) 解题报告
- CF#403(Div.2) 解题报告
- CF#410(Div.2) 解题报告
- CF Round 415 Div.2解题报告
- CF #308 Div.2 C题 Vanya and Scales 解题报告
- 0712CF解题报告
- 130720CF解题报告
- Codeforces Round #244 (Div. 2)(解题报告)
- Codeforces Round #266 (Div. 2)(解题报告)
- Codeforces Round #277 (Div. 2) 解题报告(B C)
- Codeforces Round #298 (Div. 2) 解题报告 (ABCD)
- Codeforces Round #342 (Div 2) 解题报告
- 130720CF div2解题报告
- cf 161C 解题报告
- 【解题报告】Codeforces Round #384 (Div. 2)(先占个位置里面暂时什么都没有)
- Failure [INSTALL_FAILED_OLDER_SDK], IntelliJ IDEA app编译错误
- Serializable和Parcelable的比较
- mysql简单知识点总结
- 重磅!神经网络浅讲:从神经元到深度学习
- Spring的事务 之 9.3 编程式事务 ——跟我学spring3
- CF#384 (Div.2) 解题报告
- 分布式锁的几种实现方式
- Android 4.0 Launcher2源码分析——启动过程分析
- spring boot 注解
- Wireshark使用笔记
- Linux GCC常用命令
- maven install报错:Unable to locate the Javac Compiler in
- 中文乱码问题分析
- easyUi dataGrid 数据表格(DataGrid)的特性