CF#398(Div.2) 解题报告
2017-02-18 23:29
309 查看
A
题意简述
有n个大小为1..n的物品,每一天会得到一个,物品必须由下而上按照从大到小的顺序摆放每一天会将已有的物品尽量摆放,问这n天的摆放方案
数据范围
1≤n≤100000题解
只有一个物品只有当比它大的所有物品都得到时才能摆放模拟即可
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<queue> #include<ctime> #include<cmath> #include<map> using namespace std; #define N 100005 int n,x,now; bool vis ; int main() { scanf("%d",&n); now=n; for (int i=1;i<=n;++i) { scanf("%d",&x); vis[x]=1; while (vis[now]) printf("%d ",now--); puts(""); } }
B
题意简述
接待处服务时间为0点之后ts~tf-1,每一个人需要的服务时间为t有一些人在某一个时刻来并且排队
V也会在某一个时间来,如果这个时间也有别人来,他会排在这些人的后面
求V的最小等待时间
数据范围
0≤n≤100000,ts,tf,t≤1012题解
首先判断服务是否有断层,如果有的话即在那个时刻来如果没有断层,枚举V在哪一个时间点来,有价值的时间点只有n个时间点以及两个时间点之间的断点
预处理时间点ai来的人需要办理服务到什么时间
注意n=0需要特判
算是贪心吧
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<queue> #include<ctime> #include<cmath> #include<map> using namespace std; #define LL long long #define N 100005 const LL inf=1e18; int n,Max; LL s,t,l; LL now,a ,ed ,ans,ansp; int main() { scanf("%I64d%I64d%I64d",&s,&t,&l);--t; scanf("%d",&n); if (!n) {printf("%I64d\n",s);return 0;} for (int i=1;i<=n;++i) scanf("%I64d",&a[i]); now=s;Max=n; for (int i=1;i<=n;++i) { if (a[i]<=now) now+=l,ed[i]=now-1; else {printf("%I64d\n",now);return 0;} if (now>t-l+1) {Max=i;break;} } if (ed[Max]<t-l+1) {printf("%I64d\n",ed[Max]+1LL);return 0;} ans=inf; for (int i=Max-1;i>=1;--i) if (a[i]==a[i+1]) ed[i]=max(ed[i],ed[i+1]); if (a[1]>0) { now=s-(a[1]-1LL); if (now<ans) ans=now,ansp=a[1]-1LL; } for (int i=1;i<=Max;++i) { if (ed[i]<t-l+1) { now=ed[i]+1LL-a[i]; if (now<ans) ans=now,ansp=a[i]; } if (i==Max||a[i+1]-a[i]<=1LL) continue; else { now=ed[i]+1LL-(a[i+1]-1LL); if (now<ans) ans=now,ansp=a[i+1]-1LL; } } printf("%I64d\n",ansp); return 0; }
C
题意简述
一棵有根树每一个节点有一个权值需要将这棵树断开两条边变成三棵树,并满足三棵树的权值和相等
无解-1
注意:只能将某一个节点与其父亲相连的那条边断开
数据范围
3≤n≤106,−100≤ti≤100题解
首先总权值和被3整除可以满足条件的只有两种情况
1、两棵子树权值和为sum3,并且互不包含
2、一棵子树权值和为2∗sum3,一棵子树权值和为sum3并且前者包含后者
dfs即可
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<queue> #include<ctime> #include<cmath> #include<map> using namespace std; #define N 1000005 int n,fa,root,sum,id; int tot,point ,nxt ,v ; int size ,ans[5]; bool pd,flag ; void add(int x,int y) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; } void findse(int x) { for (int i=point[x];i;i=nxt[i]) { if (size[v[i]]==sum/3) { ans[2]=v[i]; printf("%d %d\n",ans[1],ans[2]); exit(0); } findse(v[i]); } } void findsy(int x) { if (pd) return; if (size[x]==sum/3) { ans[++id]=x; pd=1; return; } for (int i=point[x];i;i=nxt[i]) findsy(v[i]); } void dfs(int x) { int cnt=0; for (int i=point[x];i;i=nxt[i]) { dfs(v[i]); size[x]+=size[v[i]]; if (flag[v[i]]) ++cnt; } if (cnt>=2) { id=0; for (int i=point[x];i;i=nxt[i]) if (flag[v[i]]) { pd=0; findsy(v[i]); if (id==2) break; } printf("%d %d\n",ans[1],ans[2]); exit(0); } if (x!=root&&(cnt||size[x]==sum/3)) flag[x]=1; if (x!=root&&size[x]==sum/3*2&&flag[x]) { ans[1]=x; findse(x); } } int main() { scanf("%d",&n); for (int i=1;i<=n;++i) { scanf("%d%d",&fa,&size[i]); sum+=size[i]; if (fa) add(fa,i); else root=i; } if (sum%3!=0) {puts("-1");return 0;} dfs(root); if (ans[1]&&ans[2]) printf("%d %d\n",ans[1],ans[2]); else puts("-1"); }
一点总结。。。
感觉最近各种傻逼→_→①认真读题!认真看数据范围!尤其是极限的情况(不光包括上界也包括下界)
②要认真想不合法的情况,加特判
③想清楚再写,非常麻烦的题不要慌,一点一点写
相关文章推荐
- Codeforces #200 (Div.2) E. Read Time 解题报告
- Codeforces Round #283(Div.2) A,B,C,D,E 解题报告
- CF#410(Div.2) 解题报告
- CF#386(Div.2) 解题报告
- codeforces #198 div.2 解题报告
- CF Round 415 Div.2解题报告
- Codeforces Round #285(Div.2) A,B,C 解题报告
- CF#403(Div.2) 解题报告
- 解题报告:codeforces #339(Div.2)B.Gena's Code
- CF#384 (Div.2) 解题报告
- Codeforces #191(Div.2)解题报告
- 【解题报告】BestCoder Round #77 (div.2)
- CF#401(Div.2) 解题报告
- BestCoder Round #77 (div.2)解题报告
- POJ 3264解题报告
- HDU 2209 翻纸牌游戏 解题报告
- Checker【解题报告】
- [LeeCode]Search for a Range, 解题报告
- 【Jason's_ACM_解题报告】Defense Lines
- [leetcode] 6. ZigZag Conversion 解题报告