ersgyegsesg
前言 :
ATC质量感觉太好了,真的是见一题学一个新东西( 与其多大cf,不如老老实实的补高质量题。而ABC我觉得对我就是一个很好的选择,因此我打算经常去回来巩固在ABC做的题,就有了做这篇博客的想法。我目前水平太弱了,2200的题就要琢磨好久,为了提升自己,目标刷1200-2200的题。当然有些题可能是我认为是这样做,但是实际上相差百出,如果有大佬不经意看到此篇并给予建议与纠正,我会十分感激您的。
我挺喜欢与各路OI/ACMer 交友的。
ABC 238
E Range Sums (板子题)
题意:一共有n个数,q次查询,每次告诉给你两个数(x,y),表示知道
ax+a(x+1)+...+a[y]的总和,问你根据q次询问后 是否能计算出a1+a2+...+an的总和
思路:这是一道差分约数的题,一般习惯性的add(x-1,y),add(y,x-1)这样建边。
sum[y]-sum[x-1]<=z sum[y]-sum[x-1]>=z 也就约束成了,sum[y]-sum[x-1]=z
map<int,int>mp; void dfs(int x){ for(int i=0;i<a[x].size();i++){ if(!mp[a[x][i]]){ mp[a[x][i]]=1; dfs(a[x][i]); } } } int main(){ cin>>n>>q; for(int i=1;i<=q;i++){ int v,u; cin>>v>>u; v--; a[v].push_back(u); a[u].push_back(v); } dfs(0); if(mp[n]){ cout<<"Yes"<<endl; }else{ cout<<"No"<<endl; } }
题意:n个学生,拥有两科成绩的排名。现在你可以自行安排人数为k个的队伍,但是如果未选中里的某个学生 两个排名都比选中队伍的任何一个学生的排名都低,则是不合法的。
有两种状态
首先是选上当前学生,选上的前两维肯定存在这样的关系
dp(i-1)(j)----->dp(i)(j+1)
那么未选中的学生就变成了min(b[i],u)
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[a[i]];
f[0][0][n+1]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=k;j++){
for(int u=0;u<=n+1;u++){
if(b[i]<u){
f[i][j+1][u]=(f[i][j+1][u] + f[i-1][j][u])%mod;
}
f[i][j][min(b[i],u)]=(f[i][j][min(b[i],u)] + f[i-1][j][u])%mod;
}
}
}
long long ans=0;
for(int i=0;i<=n+1;i++) ans=(ans + f[n][k][i])%mod;
这里有一个小技巧:就是如果我们读入bi是这样读入,那么我们在枚举的时候其实就是默认先将第一科排名进行了排序。
这题可以用hash的做法 根据: a^b^(a^b)=0来判断出现次数是否为3的倍数
因此我们不关心a和b具体是多少,只要不相等都行
for(int i=2;i<MAX;i++){ if(!v[i].empty()){ continue; } for(int j=i;j<MAX;j+=i){ int mj=j; while(mj%i==0){ mj/=i; v[j].push_back(i); } } }
原理就是 a^b^(a^b)=0 出现三次的话 就会异或成0,进而次数是3的倍数的话,异或最终一定是0
接着我们对每一个a[i]都进行这样的操作
Hi= Hi ^ X[a[i]某一个的质因子]【a[i]某一个质因子当前出现的次数%3】
uint_fast64_t seed=251902756251902756; mt19937_64 rand1(seed); vector<vector<int>>v(MAX); for(int i=2;i<MAX;i++){ if(!v[i].empty()){ continue; } for(int j=i;j<MAX;j+=i){ int mj=j; while(mj%i==0){ mj/=i; v[j].push_back(i); } } } vector<vector<long long>>x(MAX,vector<long long>(3,0)); for(int i=0;i<MAX;i++){ while(x[i][0]==0){ x[i][0]=rand1(); } while(x[i][1]==0||x[i][1]==x[i][0]){ x[i][1]=rand1(); } x[i][2]=(x[i][0] ^ x[i][1]); } vector<int>rw(n+1,0); vector<int>v1(MAX,0); for(int i=0;i<n;i++){ rw[i+1]=rw[i]; for(int j=0;j<v[a[i]].size();j++){ rw[i+1]^=x[v[a[i]][j]][v1[v[a[i]][j]]%3]; v1[v[a[i]][j]]++; } } for(int i=0;i<q;i++){ if(rw[l[i]-1]==rw[r[i]]){ cout<<"Yes"<<endl; }else{ cout<<"No"<<endl; } }
ABC 237
E - Skiing
N个城市,每个城市有自己的高度,m次查询,如果 X高于Y,则X前往Y的幸福度是HX-HY
如果 X低于Y ,X前往Y的幸福度 是 -2*(HY-HX),问从1开始前往其他城市能得到的最大幸福度是多少
考虑以下几种情况
H1>H2>H3 此时幸福度为(H1-H2)+(H2-H3)=H1-H3
H1<H2<H3 此时幸福度为 -2(H2-H1)-2(H3-H2)=-2(H3-H1)=H1+H1-H3-H3
H1>H2<H3 此时幸福度为(H1-H2)-2(H3-H2)=H1+H2-H3-H3
H1< H2 >H3 此时幸福度为 -2(H2-H1)+(H2-H3)=H1+H1-H2-H3
由此我们可以得到,加入HX>=HY,我们就建边时 边权为0,如果HX<HY,我们就建边为HY-HX
那么1到每一个点的长度就是H1-Hi -di
for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; if(b[x]>=b[y]){ a[x].push_back(make_pair(y,0)); a[y].push_back(make_pair(x,b[x]-b[y])); }else{ a[x].push_back(make_pair(y,b[y]-b[x])); a[y].push_back(make_pair(x,0)); } } for(int i=1;i<=n;i++){ long long haha=-d[i]; ans=max(ans,b[1]-b[i]+haha); } cout<<ans<<endl;
F - |LIS| = 3
dp[n][长度为1序列结尾的结尾最小数][长度为2序列结尾的最小数][长度为3序列结尾的最小数]
比如说 2,4,4,2 这是一个dp(5)(2)(4)(空)的情况
但是我那么如果加一个1 则就变成了dp(6)(1)(2)(4),因此上面的方案数完全可以归到此方案中
上升长度是3,因此我们只需要枚举上升序列的结尾三个数即可进行转移
for(int x=1;x<=min(j,m);x++){ dp[i][x][k][u]=(dp[i][x][k][u] + dp[i-1][j][k][u])%mod; } for(int x=j+1;x<=min(k,m);x++){ dp[i][j][x][u]=(dp[i][j][x][u] + dp[i-1][j][k][u])%mod; } for(int x=k+1;x<=min(u,m);x++){ dp[i][j][k][x]=(dp[i][j][k][x] + dp[i-1][j][k][u])%mod; }
ABC 236
一共有n个数,对于每个i,第i个和第i+1个必须选择一个数,问选出的最大平均数以及选出的最大中位数是多少?
while(r-l>1e-4){ double mid=(l+r)/2; vector<double>dp(n+1); for(int i=1;i<=n;i++){ dp[i]=-1e18; if(i<3){ dp[i]=0; } if(i>1){ dp[i]=max(dp[i-1],dp[i]); } if(i>2){ dp[i]=max(dp[i],dp[i-2]); } dp[i]+=a[i]-mid; } if(max(dp[n],dp[n-1])>=0){ l=mid; }else{ r=mid; } }
再来考虑中位数,如果x作为这个长度为y序列的中位数,那么一定有1-(y/2)个数小于等于x,且(y/2)+1-y是大于等于x的,因此我们类比平均数一样来推出方程。比如 ai>=mid ,dpi++,ai<mid,dpi--。如果最后总和大于0,那么就可以得到中位数为mid的情况
int L=0,R=1e9; while(L!=R){ int mid=(L+R+1)/2; vector<int>dp(n+2); for(int i=1;i<=n;i++){ dp[i]=-1e9; if(i<3){ dp[i]=0; } if(i>1){ dp[i]=max(dp[i],dp[i-1]); } if(i>2){ dp[i]=max(dp[i],dp[i-2]); } if(a[i]>=mid){ dp[i]++; }else{ dp[i]--; } } if(max(dp[n],dp[n-1])>0){ L=mid; }else{ R=mid-1; } }
sort(a+1,a+cnt+1); for(int i=1;i<(1<<n);i++){ for(int j=62;j>=0;j--){ if(!(a[i].second>>j))continue; if(!p[j]){ p[j]=a[i].second; ans+=a[i].first; break; }else{ a[i].second^=p[j]; } } }

浙公网安备 33010602011771号