Time:2018.5.5 8:15-13:15
A
题意
对每一组序列,询问是否为山峰数组
分析
模拟即可
B
题意
给两个长度为n的序列A_i,B_i,可以给每一个A_i+k,问最多有多少个A_i==B_i
分析
上下做差,查询出现次数最多的数即可
C
题意
分析
D
题意
给一个长度为n的括号序列,每个括号都有一个V_i,如果S_k='(' && S_k+1==')',最终的答案可以加V_i*V_i+1,问最后的最大值
分析
ym:状态一: dp[i][j]:表示第i个(匹配到第j个)的情况下的最大值
状态二: dp[i][j]:表示还剩下i个(和j个)的情况下的最大值,考虑从右到左确定每个( 的位置 1、他右边所有的(都固定了,2、他右边的)都不会影响后续
#include<bits/stdc++.h>
#define ll long long
using namespace std;
char s[1005];
ll dp[1005][1005],sum[1005],num[1005];
int l[1005];
int main()
{
int t,n,cnt,l1,l2;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
dp[i][j]=-1000000007;
scanf("%s",s+1);
cnt=l1=l2=0;
for(int i=1;i<=n;i++){
if(s[i]==')')
cnt++;
else
l[i-cnt]=cnt;
}
for(int i=1;i<=n;i++){
if(s[i]=='('){
l1++;
scanf("%lld", &num[l1]);
}
else{
l2++;
scanf("%lld",&sum[l2]);
sum[l2]+=sum[l2-1];
}
}
for(int i=0;i<=l2;i++)
dp[l1][i]=0;
for(int i=l1;i>0;i--){
for(int j=l[i];j<=l2;j++)
dp[i-1][j]=max(dp[i-1][j],dp[i][j]+(sum[j]-sum[l[i]])*num[i]),cout<<i<<' '<<dp[i-1][j]<<endl;;
for(int j=l2-1;j>=0;j--)
dp[i-1][j]=max(dp[i-1][j],dp[i-1][j+1]);
}
printf("%lld
",dp[0][0]);
}
return 0;
}
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <iostream>
#include <cmath>
#include <queue>
#include <ctime>
using namespace std;
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define pb push_back
#define fi first
#define se second
#define ll long long
#define sz(x) (int)(x).size()
#define pll pair<long long,long long>
#define pii pair<int,int>
#define pq priority_queue
char s[100000];
ll v[100000];
ll sum[100000];
ll dp[1010][1010];
int main(){
//freopen("in","r",stdin);
//freopen("out","w",stdout);
//clock_t start_time=clock();
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
scanf("%s",s+1);
int pre=0;
for(int i=1;i<=n;i++){
scanf("%lld",&v[i]);
if(s[i]==')')sum[i]=sum[i-1]+v[i];
else sum[i]=sum[i-1];
}
for(int i=n;i>=1;i--){
if(s[i]==')')continue;
for(int j=n;j>=i;j--){
dp[i][j]=dp[pre][j]+v[i]*(sum[j]-sum[i]);
if(j<n && dp[i][j+1]>dp[i][j])dp[i][j]=dp[i][j+1];
}
for(int j=i-1;j>=1;j--){
dp[i][j]=dp[i][j+1];
}
pre=i;
}
printf("%lld
",dp[pre][1]);
}
//clock_t end_time=clock();
//cout<< "Running time is: "<<static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000<<"ms"<<endl;//输出运行时间
return 0;
}
E
题意
分析
F
题意
给出 ,现有n个A_i,m个P_i,对于每一个P_i该公式的和,问全部加起来的和 ( n,m<=5e5,A_i,P_i <= 1e9)
分析
ym:考虑到log函数变化缓慢,在此题中最大也不过32,故对于同一个p有很多数,向上取整后的值相等,预处理出分数和,二分查找即可
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=5e5+7; const int mod=1e9; int n,m,a[maxn]; int p[maxn]; int fac[maxn][33]; int main() { int t; cin>>t; while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=m;i++) scanf("%d",&p[i]); sort(a+1,a+n+1); for(int i=1;i<=n;i++) { for(int j=1;j<=32;j++) { fac[i][j]=(fac[i-1][j]+a[i]/j)%mod; } } ll ans=0; int st=0; for(int i=1;i<=m;i++) { st=0; ll now=p[i]; ll sum=0; int num=1; while(1) { int id=upper_bound(a+1,a+n+1,now)-a; if(id==n+1) break; sum=(sum+fac[id-1][num]-fac[st][num])%mod; num++; now*=p[i]; st=id-1; } sum=(sum+fac[n][num]-fac[st][num])%mod; ans=(ans+sum*i)%mod; } printf("%lld ", (ans+mod)%mod); } return 0; }
G
题意
分析
H
题意
分析
I
题意
分析
J
题意:将1到n分为两个阵营
ym:偶数的话一定可以分,贪心分数字即可
czh:奇数一定不能分,从后往前贪心
K
题意
先从3*M中抽一个麻将作为幸运牌,然后从3*M+1中抽n个麻将排序
如果n个麻将中有幸运麻将,则将幸运麻将放最左边
白板在排序时,把它的牌面当作是幸运麻将的牌面
分析
czh: 分类讨论+模拟+猜题
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+5; int num[maxn],n,m,pos,ans; int main() { int T; cin>>T; for(int i=1;i<=T;i++) { pos=0; cin>>n>>m; for(int j=1;j<=n;j++) { int b; char k; cin>>k; if(k=='W') { pos=j; } else if(k=='C') { cin>>b; num[j]=b; } else if(k=='B') { cin>>b; num[j]=m+b; } else if(k=='D') { cin>>b; num[j]=m*2+b; } } if(n==1)//一张牌时,无论这张牌是什么,所有牌都可能是幸运牌 { cout<<3*m<<endl;; } else if(n==2) { if(pos==1)//当W在1号位置时,比2号牌小的全是幸运牌,不包括2号牌 cout<<num[2]-1<<endl; else if(pos==2)//比1号牌大,包括1号牌 cout<<3*m-num[1]+1<<endl; else {//没有W if(num[1]>num[2])//乱序了,只有1张幸运牌 cout<<1<<endl; else//有序,则除了第二张都是 cout<<3*m-1<<endl; } }//三张及以上的幸运牌 else { if(pos==1) { cout<<num[2]-1<<endl; } else if(pos==2) { cout<<num[3]-num[1]<<endl; } else if(pos==0) { if(num[1]>num[2]) cout<<1<<endl; else { cout<<3*m-n+1<<endl; } } else { if(num[1]>num[2]) cout<<1<<endl; else { if(pos==n) cout<<3*m-num[pos-1]<<endl; else cout<<num[pos+1]-num[pos-1]-1<<endl; } } } } return 0; }
L
结构体排个序就好了
M
签到
Summary
Ym:躺好别送,B题疯狂wa,一度坚信自己一开始想法是right,前期czh做的不错,在ym B题wa的时候稳住了局面,没有大崩盘,D题dp转移有点难想,K题没读懂,F题多读读没准还有机会?
Czh:后期有两个小时没有一点思绪。算法题做不动,实力不足啊