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\n",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\n",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\n", (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:后期有两个小时没有一点思绪。算法题做不动,实力不足啊