博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019 CCPC-Wannafly Winter Camp Day4(Div2, onsite)
阅读量:4361 次
发布时间:2019-06-07

本文共 9070 字,大约阅读时间需要 30 分钟。

slove 6/11

 

Code:zz

Thinking:zz

贪心即可。这条路线里,点n1和点n2肯定是相连的,接下来,点(n-1)1和点(n-1)2分别是和n1和点n2相连的,一共有两种情况,选择距离短的即可,就这样一直往前贪心。

//#pragma comment(linker, "/STACK:102400000,102400000")#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 0x3f3f3f3f;const double EI = 2.71828182845904523536028747135266249775724709369995957496696762772407663035354594571382178525166427;const double PI = 3.141592653589793238462643383279;using namespace std;struct s{ long long x1,y1,x2,y2;}z[100010];inline long long dis(long long x1,long long y1, long long x2,long long y2){ long long z1 = x1 - x2; long long z2 = y1 - y2; if(z1 < 0) { z1 = -z1; } if(z2 < 0) { z2= -z2; } return z1 + z2;}int main(void){ //ios::sync_with_stdio(false); int n,m,i; long long ans; while(~scanf("%d %d",&n,&m)) { for(i = 1;i <= n;i++) { scanf("%lld %lld %lld %lld",&z[i].x1,&z[i].y1,&z[i].x2,&z[i].y2); } //printf("1111\n"); ans = 0; ans += dis(z[n].x1,z[n].y1,z[n].x2,z[n].y2); //printf("2222 %lld\n",ans); for(i = n - 1;i >= 1;i--) { ans += min(dis(z[i].x1,z[i].y1,z[i + 1].x1,z[i + 1].y1) + dis(z[i].x2,z[i].y2,z[i + 1].x2,z[i + 1].y2) ,dis(z[i].x1,z[i].y1,z[i + 1].x2,z[i + 1].y2) + dis(z[i].x2,z[i].y2,z[i + 1].x1,z[i + 1].y1)); /*printf("%d %lld\n",i,min(dis(z[i].x1,z[i].y1,z[i + 1].x1,z[i + 1].y1) + dis(z[i].x2,z[i].y2,z[i + 1].x2,z[i + 1].y2) ,dis(z[i].x1,z[i].y1,z[i + 1].x2,z[i + 1].y2) + dis(z[i].x2,z[i].y2,z[i + 1].x1,z[i + 1].y1)));*/ } printf("%lld\n",ans); } return 0;}
View Code

 

Code:kk

Thinking:kk zz

用树形dp找每个联通块 树的直径,树的直径大于等于4的就肯定不行,有孤立的点也不行,就这样。

然而别人都是用结论做的,每条边连上去后,边两边的点只能有一个入度大于1.

我就是个弟弟。

#include
#define CLR(a,b) memset(a,b,sizeof(a))using namespace std;typedef long long ll;const int maxn=200010;const int inf=0x3f3f3f3f;int fa[maxn],n,m;bool vis[maxn];int head[maxn],tot;struct edge{ int to,Next;}a[maxn<<2];void init() { CLR(vis,0); CLR(head,-1),tot=0;}void addv(int u,int v){ a[++tot].to=v; a[tot].Next=head[u]; head[u]=tot;}int u,v,maxx;int dfs(int u,int deep,int fa){// printf("u:%d\n",u); int fmax=0,smax=0; vis[fa]=1; for(int i=head[u];i!=-1;i=a[i].Next) { int v=a[i].to; if(v==fa)continue; if(vis[v]==1) { maxx=inf; return inf; } vis[v]=1; int tep=dfs(v,deep+1,u); if(fmax==0)fmax=max(fmax,tep); else if(smax==0){ smax=tep; if(fmax
fmax){ smax=fmax,fmax=tep; }else if(tep>smax){ smax=tep; } }// printf("u:%d\n",u);// printf("maxx:%d\n",maxx);// printf("fmax:%d smax:%d\n",fmax,smax); maxx=max(maxx,max(fmax+smax,fmax+deep)); if(maxx>=inf)return inf; return fmax+1;}int main() { while(cin>>n>>m) { init(); while(m--) { scanf("%d%d",&u,&v); addv(u,v),addv(v,u); } for(int i=1;i<=n;i++) { if(vis[i]==0) { dfs(i,0,-1); } if(maxx>=3) { break; } } for(int i=1;i<=n;i++) { if(vis[i]==0){ puts("No\n"); return 0; } } if(maxx>=3){ printf("No\n"); }else{ puts("Yes"); } }}
View Code

 

题解待补。

 

Code:zz

Thinking:zz

马是走日字的,因此走一步后,他所在的格子的颜色和上一格肯定是不一样的,因此,如果他的起点颜色和终点颜色是一样的,那么肯定是No;如果颜色是一样的,那么只要起点和终点是互相可达的,那么是Yes,反之是No。除了3*3的棋盘和2*n的棋盘需要判断是否可达外,其他都能可达。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const int maxn = 0x3f3f3f3f;const double EI = 2.71828182845904523536028747135266249775724709369995957496696762772407663035354594571382178525166427;const double PI = 3.141592653589793238462643383279;using namespace std;int main(void){ //ios::sync_with_stdio(false); int n,m,s1,s2,e1,e2; while(~scanf("%d %d",&n,&m)) { scanf("%d %d %d %d",&s1,&s2,&e1,&e2); if(n > m) { int r = n; n = m; m = r; } if(n == 3 && m == 3) { if(s1 == 2 && s2 == 2 || e1 == 2 && e2 == 2) { printf("No\n"); } else if((s1 + s2) % 2 == (e1 + e2) % 2) { printf("No\n"); } else { printf("Yes\n"); } } else if(n == 2) { if(s1 > 2 || e1 > 2) { int r = e1; e1 = e2; e2 = r; r = s1; s1 = s2; s2 = r; } if(e1 == s1) { printf("No\n"); } else { if((abs(e2 - s2) - 2) % 4 == 0) { printf("Yes\n"); } else { printf("No\n"); } } } else { if((s1 + s2) % 2 == (e1 + e2) % 2) { printf("No\n"); } else { printf("Yes\n"); } } } return 0;}
View Code

 

Code:pai爷

Thinking:pai爷

dp,注意到上凸和下凸的答案是一样的,从下到大枚举插入的数用组合数搞一下方案

#include
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;const int p=1e9+7;ll dp[1010],sum[1010],fac[1010],inv[1010];ll qpow(ll a,ll b){ ll ret=1;a%=p; while(b) { if(b&1) ret=ret*a%p; b/=2;a=a*a%p; } return ret;}ll C(ll n,ll m){ if(m>n) return 0; return 1ll * fac[n] * inv[m] % p * inv[n - m] % p;} int main(){ fac[0]=1;inv[0]=1; for(int i=1;i<=1000;i++) { fac[i]=1ll*fac[i-1]*i%p; inv[i]=qpow(fac[i],p-2); } int n; scanf("%d",&n); dp[0]=dp[1]=1; sum[1]=1; for(int i=2;i<=n;i++) { sum[i]=0; for(int j=1;j<=i;j++) { sum[i]=(sum[i]+dp[j-1]*dp[i-j]%p*C(i-1,j-1)%p) %p; } dp[i]=sum[i]*qpow(2,p-2)%p; } printf("%lld\n",dp[n]); return 0;}
View Code

 

Code:pai爷

Thinking:pai爷

一个裸的贪心,计算一下式子枚举保留了k个物品,之后sort一下。取前k个。

#include
#include
#include
#include
#include
#include
using namespace std;struct node{ int c,id;}sum[1010];int a[1010],b[1010];long long p,q,ans=0;int n;bool cmp(node a,node b){ return a.c>b.c;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); } for(int k=1;k<=n;k++) { p=0;q=0; for(int i=1;i<=n;i++) { sum[i].c=a[i]-k*b[i]; sum[i].id=i; } sort(sum+1,sum+1+n,cmp); for(int i=1;i<=k;i++) { p=p+a[sum[i].id]; } for(int i=k+1;i<=n;i++) { q=q+b[sum[i].id]; } ans=max(ans,p+1ll*q*k); } printf("%lld\n",ans);}
View Code

 

Code:kk zz

Thinking:kk

选取的两条链交点是x,所以就是选取和x有关的两条大链,而且查询次数非常少,所以就是求每个节点的四条子链的总和,如果子链为负数,则不取。

#include
#define CLR(a,b) memset(a,b,sizeof(a))using namespace std;typedef long long ll;const int maxn=100010;const int inf=0x3f3f3f3f;int n,m;bool vis[maxn];int head[maxn],tot;struct edge{ int to,Next;}a[maxn<<2];ll val[maxn];ll pre[40];void init() { CLR(vis,0); CLR(head,-1),tot=0; pre[1]=1; for(int i=2;i<=30;i++) { pre[i]=pre[i-1]*2; }}void addv(int u,int v){ a[++tot].to=v; a[tot].Next=head[u]; head[u]=tot;}int u,v;ll son[maxn][4];ll dfs(int u,int fa){ for(int i=head[u];i!=-1;i=a[i].Next) { int v=a[i].to; if(v==fa)continue; ll tep=dfs(v,u); int flag = 1; for(int j=0;j<4;j++) { if(son[u][j]==0){ son[u][j]=tep; flag = 0; break; } } sort(son[u],son[u]+4); if(son[u][0]
>n) { init(); for(int i=1;i<=n;i++) { scanf("%d",&u); if(u>=0) { val[i]=pre[u]; }else{ val[i]=-pre[-u]; } } for(int i=1;i
>q; while(q--) { memset(son,0,sizeof(son)); scanf("%d",&u); dfs(u,-1); ll ans=val[u]; for(int i=0;i<4;i++) { ans+=max((ll)0,son[u][i]); //printf("%lld ",son[u][i]); } //printf("\n"); //printf("%lld\n",ans); int op= (ans<0); if(ans < 0) { ans = -ans; } int cc[100],cnt = 0; while(ans) { cc[cnt++] = ans %2; ans /= 2; } if(op) { printf("-"); } if(cnt == 0) { printf("0"); } for(int i = cnt - 1;i >= 0;i--) { printf("%d",cc[i]); } printf("\n"); } }}
View Code

 


 

赛后总结:

kk:今天有蛮多图的题目的,但是读c题的题意没读懂,别人用简单结论一小时不到就做出的题目,我写了树形dp求树的直径两小时后才ac,k题也是个树形dp的题,套了上一题的代码,结果int忘记改成long long了,wawawawawa,贼菜,把队友的腿都给抱断了。

pai爷:今天状态很差,那道DP题一直在想DP[i][j]表示枚举到第i个位置填了j的方案数,但是无法满足排列,想了很久才写出来,之后那道欧拉回路的时间不多了,找规律的题还是缺少一个系统的操作,最后时刻还是没有写出来。

zz:今天很快写掉了两个签到题,然后帮队友看c题,看了很久没看出来,后来发现题读错了,然后又一起看了k,做法很快就出了,代码打出来以后要出了很多bug,wa了很多次,改了很久才过,写代码还是要仔细点,不然小bug改到死。

转载于:https://www.cnblogs.com/mountaink/p/10311712.html

你可能感兴趣的文章
hdu--1540 Tunnel Warfare(线段树+区间合并)
查看>>
通过命令给Linux(CentOS)分区
查看>>
Sprint1规划暨first stand up meeting
查看>>
python接口自动化3-自动发帖(session)
查看>>
复杂问题的简单抽象:魔兽世界中的兔子们
查看>>
那些美到极致的语言!
查看>>
Xamarin的不归路-ios模拟器没有键盘
查看>>
【云笔记】群晖DS218+ NoteStation 折腾
查看>>
jdk安装配置
查看>>
四、RocketMq简单的消费者和生产者(示例代码)
查看>>
json介绍
查看>>
Maven编译unmappable character for encoding Cp1252问题
查看>>
xftp上传文件失败,执行程序发现磁盘满了:No space left on device
查看>>
duplicate symbols for architecture i386 问题?
查看>>
[BZOJ]1027 合金(JSOI2007)
查看>>
poj 1696 Space Ant (几何 : 叉积 应用 + dfs)
查看>>
MySQL:按前缀批量删除表格
查看>>
Route学习笔记之Area的Route注册
查看>>
构建之法--软件工程师自我测评表
查看>>
电子书搜索
查看>>