【CF】Codeforces Round #530 (Div. 2)
好菜呀,本来感觉可以涨分的,,没想到C题水题有个地方G掉了fst了orz
A题
水题模拟#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
int w,h;
int u1,d1,u2,d2;
int main() {
scanf("%d%d",&w,&h);
scanf("%d%d%d%d",&u1,&d1,&u2,&d2);
for(int i=h;i>=1;i--) {
w += i;
if(d1==i) w -= u1;
if(d2==i) w -= u2;
if(w<0) w = 0;
}
printf("%d",w);
}
B题
水题模拟#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main() {
int n;
cin>>n;
int r = sqrt(n);
int o = (n+r-1)/r;
cout<<r+o<<endl;
}
C
水题模拟,然而本来应该for i in range[1,tot]的,然而我直接写了t+1就挂掉了orz#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 305;
int k,n;
char ss[maxn];
char t[maxn];
int tot;
void tuichu() {
puts("Impossible");
exit(0);
}
int main() {
scanf("%s%d",&ss[1],&k);
n = strlen(ss+1);
int xin = 0; int liu = 0;
int cnt = 0;
for(int i=1;i<=n;i++) {
if(ss[i]!='?'&&ss[i]!='*') cnt++;
else {
if(ss[i]=='?') liu++;
else xin++;
}
}
if( (cnt-xin-liu)>k||(cnt<k&&(!xin)) ) tuichu();
if(xin) {
int cl = cnt - xin - liu;
int cp = k - cl;
bool nw = 0;
for(int i=1;i<=n;i++) {
if(ss[i]=='*') {
if(!nw) {
for(int j=1;j<=cp;j++) t[++tot] = ss[i-1];
nw = 1;
}
--tot;
}
else if(ss[i]=='?') {
--tot;
} else t[++tot] = ss[i];
}
} else {
int cl = cnt - liu;
int cp = k - cl;
for(int i=1;i<=n;i++) {
if(ss[i]=='?') {
if(cp) --cp;
else --tot;
}
else t[++tot] = ss[i];
}
}
for(int i=1;i<=tot;i++) {
putchar(t[i]);
}
}
D
有一颗有根树n1e5,每个点都记了从根到那个点路径的权值和,但是深度为偶数的店的权值和为-1(自己去填),点权值都是未知,填树上的点权值,使得成立并且可以权值总和最小,不可以的输出-1 dfs一次,记录路径上的权值最大值,如果是奇数深度点,ANS+=S[x]-MX (S[x]为根到当前点权值和),偶数的话尽可能在满足题意的情况下选最大的填。如果往上的最大值大于当前S,无解。#include<iostream>
#include<algorithm>
#include<cstdio>
#define int long long
using namespace std;
const int maxn = 2e5+5;
int en[maxn],nt[maxn],la[maxn],owo;
void adg(int x,int y) {
en[++owo]=y; nt[owo]=la[x]; la[x]=owo;
}
int n;
int ANS;
bool flag;
int S[maxn];
void dfs(int x,int dp,int mx) {
if(dp==1) {
if(mx>S[x]) { flag = 1; return; }
ANS += S[x] - mx;
for(int it=la[x];it;it=nt[it]) {
int y = en[it];
dfs(y,dp^1,max(mx,S[x]));
}
} else {
if(!la[x]) return;
int mi = 0x3f3f3f3f;
for(int it=la[x];it;it=nt[it]) {
mi = min(S[en[it]],mi);
}
if(mi<mx) { flag = 1; return; }
ANS += mi - mx;
for(int it=la[x];it;it=nt[it]) {
int y = en[it];
dfs(y,dp^1,mi);
}
}
}
main() {
scanf("%I64d",&n);
for(int i=2;i<=n;i++) {
int x; scanf("%I64d",&x);
adg(x,i);
}
for(int i=1;i<=n;i++) {
scanf("%I64d",&S[i]);
}
dfs(1,1,0);
if(!flag) printf("%I64d",ANS);
else puts("-1");
}
E
真的看不懂题意orz orz orz 咕咕咕了F
题意:给你一棵树,每个节点上有若干饼干,并且给出每个节点上吃一块饼干需要多少时间,同时给出走过一条边所需时间。 总时限为 T,两个人轮流进行操作: Mitya从当前节点选择一个子节点向下走,或者直接结束游戏并往根回动吃饼干; Vasya割断当前节点到其某个子节点的边,或者什么都不做。 问Mitya可以吃到的最多的多少块饼干。 题解:可以想到类似博弈里面,mitya的当前节点下面有若干个子树,那么vasya一定会切除掉最终会使得答案最大的那一个子树.同时对于原题中树上往回走操作考虑起来很迷,我们不如看做往下走的时候边花的时间*2就可以了.这样对于一个点就有两种选法,一个走到他次大的子树中去,一个在这个地方结束(看做把一路上的饼干收集起来,现在开始吃,回溯又把当前节点饼干放回去)计算吃饼干. 在计算某一个时间吃最多的饼干的时候,利用线段树维护.#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cmath>
#define int long long
using namespace std;
const int maxn = 2e6+5;
const int inf = 1e6;
int n,T;
int len[maxn],nt[maxn],en[maxn],la[maxn],owo;
void adg(int x,int y,int z) {
en[++owo]=y; nt[owo]=la[x]; la[x]=owo; len[owo] = z;
}
int NUM[maxn],TM[maxn];
struct node{
node *ls,*rs; int sumnum,sumtim;
}z[maxn],*rt;int ztot;
void upd(node *&p) {
p->sumnum = p->ls->sumnum + p->rs->sumnum;
p->sumtim = p->ls->sumtim + p->rs->sumtim;
return;
}
void maketree(node *&p,int l,int r) {
p = &z[++ztot];
if(l==r) return;
int mid = (l+r)>>1;
maketree(p->ls,l,mid); maketree(p->rs,mid+1,r);
}
void addseg(node *&p,int l,int r,int x,int tt) {
if(l==r) {
p->sumnum += tt; p->sumtim += x*tt;
return;
}
int mid = (l+r)>>1;
if(x<=mid) addseg(p->ls,l,mid,x,tt);
else addseg(p->rs,mid+1,r,x,tt);
upd(p);
}
int query(node *&p,int l,int r,int tt) {
if(p->sumtim<=tt) return p->sumnum;
if(l==r) return min(tt/l,p->sumnum);
int mid = (l+r)>>1;
if(p->ls->sumtim>=tt) return query(p->ls,l,mid,tt);
else return p->ls->sumnum + query(p->rs,mid+1,r,tt-p->ls->sumtim);
}
int dfs(int x,int t) {
int mx1 = 0; int mx2 = 0;
addseg(rt,1,inf,TM[x],NUM[x]);
int orz = query(rt,1,inf,t);
for(int it=la[x];it;it=nt[it]) {
int y = en[it];
if(len[it]*2>=t) continue;
int oo = dfs(y,t-2*len[it]);
if(oo>mx1) mx2 = mx1 , mx1 = oo;
else if(oo>mx2) mx2 = oo;
}
addseg(rt,1,inf,TM[x],-NUM[x]);
if(x==1) return max(orz,mx1);
else return max(orz,mx2);
}
main() {
scanf("%I64d%I64d",&n,&T);
for(int i=1;i<=n;i++) {
scanf("%I64d",&NUM[i]);
}
for(int i=1;i<=n;i++) {
int tm;
scanf("%I64d",&TM[i]);
}
for(int i=2;i<=n;i++) {
int y,le;
scanf("%I64d %I64d",&y,&le);
adg(y,i,le);
}
// cerr<<"233"<<endl;
maketree(rt,1,inf);
printf("%I64d",dfs(1,T));
}