2019佳木斯集训 Day2
T1
本次考试的第一题,比较简单
思路:每出现一个左括号就反复化为红色和蓝色
使红蓝的两种括号会最大化的分开,然后分别测定深度
取max即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,tip,qwq,l,r,ans; 4 char s[200010]; 5 bool a[200010]; 6 bool color[200010]; 7 bool vis[200010]; 8 int b[200010]; 9 bool ac; 10 int main(){ 11 scanf("%d",&n); 12 for(register int i=1;i<=n;i++){ 13 cin>>s[i]; 14 if(s[i]=='(') a[i]=1; 15 else a[i]=0; 16 } 17 for(register int i=1;i<=n;i++){ 18 if(!ac&&a[i]==1) color[i]=1,ac=1,b[++qwq]=color[i]; 19 else if(ac&&a[i]==1) color[i]=0,ac=0,b[++qwq]=color[i]; 20 if(a[i]==0){ 21 color[i]=b[++tip]; 22 } 23 } 24 //for(register int i=1;i<=n;i++) printf("%d ",color[i]); 25 for(register int i=1;i<=n;i++){ 26 if(color[i]==1&&a[i]==1) l++; 27 else if(color[i]==1&&a[i]==0) l--; 28 else if(color[i]==0&&a[i]==1) r++; 29 else if(color[i]==0&&a[i]==0) r--; 30 ans=max(ans,max(l,r)); 31 } 32 printf("%d",ans); 33 return 0; 34 }
T2
本次考试的最难题(我认为滴~)
思路:随便找一个点作为根节点,把以所有点为根的子树
大小求出来,以上用一个深搜实现,然后再用一个深搜,以根节点
的每一个子节点假设为真实的出发点我们还可以发现一个式子
就是总点数-当前的子树大小*2是ans的增量,所以下一个深搜就
搞这件事就可以了
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct node{ 4 int nxt,to; 5 }edge[2000010]; 6 int head[2000010]; 7 int n,x,y,cnt; 8 long long ans; 9 long long ac=2; 10 int tree[2000010]; 11 inline void addedge(int from,int to){ 12 cnt++; 13 edge[cnt].to=to; 14 edge[cnt].nxt=head[from]; 15 head[from]=cnt; 16 } 17 void dfs(int now,int before){ 18 tree[now]=1; 19 for(register int i=head[now];i;i=edge[i].nxt){ 20 if(edge[i].to==before) continue; 21 dfs(edge[i].to,now); 22 tree[now]+=tree[edge[i].to]; 23 } 24 } 25 void true_ans(int now,int before,long long nowans){ 26 ans=max(ans,nowans); 27 for(register int i=head[now];i;i=edge[i].nxt){ 28 if(edge[i].to==before) continue; 29 true_ans(edge[i].to,now,nowans+n-ac*tree[edge[i].to]); 30 } 31 } 32 int main(){ 33 scanf("%d",&n); 34 for(register int i=1;i<n;i++){ 35 scanf("%d%d",&x,&y); 36 addedge(x,y); 37 addedge(y,x); 38 } 39 dfs(1,0); 40 for(register int i=1;i<=n;i++) ans+=tree[i]; 41 true_ans(1,0,ans); 42 printf("%lld",ans); 43 return 0; 44 }
T3
不算非常难的一道题,但是有很多细节,而且有玄学的错误!!!
(以后long long用位运算注意点!!)
思路:每输入一辆车,就二分求一下车需要的最小油量,然后
等所有的点都求完再取最小值的最大值即可
1 #include <bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 int n,m; 5 int a[500]; 6 int s,f,c,r,trueans; 7 8 inline bool check(int x){ 9 int xx=x,rr=0; 10 for(register int j=s+1;j<=f;j++){ 11 if(xx<(a[j]-a[j-1])*c) rr++,xx=x; 12 if(rr>r) return false; 13 xx-=(a[j]-a[j-1])*c; 14 } 15 return true; 16 } 17 int ef(int L,int R){ 18 if(R==L) return L; 19 int mid=L+R; 20 mid/=2; 21 if(check(mid)) return ef(L,mid); 22 else return ef(mid+1,R); 23 } 24 signed main() 25 { 26 scanf("%lld%lld",&n,&m); 27 for(register int i=1;i<=n;i++) scanf("%lld",&a[i]); 28 for(register int i=1;i<=m;i++) 29 { 30 int ac=0,nowans=0; 31 scanf("%lld%lld%lld%lld",&s,&f,&c,&r); 32 if(trueans&&check(trueans))continue; 33 for(register int j=s+1;j<=f;j++)ac=max(a[j]-a[j-1],ac); 34 nowans=ef(ac*c,(a[f]-a[s])*c); 35 trueans=max(trueans,nowans); 36 } 37 printf("%lld\n",trueans); 38 }
Day2 score:100 rank 22
end;