b.Linear Approximation - AtCoder arc100_a - Virtual Judge
思路:数学或者三分,一开始用的三分,没解出来,在这里解一下
代码:
#include<bits/stdc++.h>
#define FIO ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef long double ld;
void test_case()
{
ll n;
cin>>n;
ll a[n];
ll mx=0;
for(int i=0;i<n;i++)cin>>a[i],mx=max(mx,a[i]);
ll low=-1e12,high=1e12;
ll ans=4e18;
for(int i=0;i<=300;i++)//由于pow(2,300)大于了2e12,所以必定能把这两个区间搜完
{
ll m1=low+(high-low)/3;
ll m2=high-(high-low)/3;
ll fm1=0;
ll fm2=0;
for(int j=0;j<n;j++)fm1+=abs(a[j]-(m1+j+1));
for(int j=0;j<n;j++)fm2+=abs(a[j]-(m2+j+1));
ans=min(ans,fm1);
ans=min(ans,fm2);//过程中记录了最小值
if(fm1<fm2)high=m2-1;
else low=m1+1;
}
cout<<ans;
}
int main()
{
FIO
int t;
t=1;
// cin>>t;
while(t--)
{
test_case();
}
}
d.AtCoder arc100_b
思路:带一点三分的思想,定义第一个区间范围为 1 − i ;第二个区间范围为 i − j ;第三个区间范围为 j − k ;第四个区间范围为 k − n
我们枚举 j 从 2至 ( n − 1 ) ,那 i和 k 一定是把 1 − ( j − 1 ) ,j − n 这两个区间分最点的点。
这种方法的时间复杂度是 O ( n ) 不会超时。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
#define int long long
int a[maxn];
int sum[maxn];
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
int ans=2100000000;
for(int i=1,j=2,k=3;j<n;j++){
while(i+1<j&&abs(sum[j]-2*sum[i])>abs(sum[j]-2*sum[i+1]))i++;
while(k+1<n&&abs(sum[n]-2*sum[k]+sum[j])>abs(sum[n]-2*sum[k+1]+sum[j]))k++;
ans=min(ans,max({sum[i],sum[j]-sum[i],sum[k]-sum[j],sum[n]-sum[k]})-min({sum[i],sum[j]-sum[i],sum[k]-sum[j],sum[n]-sum[k]}));
}
cout<<ans;
}
e.Unlucky Numbers - CodeForces 1808C - Virtual Judge
题解:可以考虑暴力枚举这个数里最大的数位(y)和最小的数位(x),然后只需要判断只使用 [x,y]内组成的数是否有存在在 [l,r]内的。
一种做法就是数位 dp,分别限制一下上下界或者差分一下判断数量,但是这太麻烦了。
我们其实可以考虑直接用 [x,y]组成大于等于 l𝑙 的最小的数,如果这个数小于等于 r𝑟 则证明有解。
这个解法很显然是正确的。
fAir Conditioners - CodeForces 1547E - Virtual Judge
思路:由于i位置的温度必定与相邻两个位置的其中一个温度具有连续性,一开始考虑到给出的空调点中某些位置是无效的,并且,空调的温度会向两边扩展,每一个点的温度由该点是否有空调,左侧空调和右侧空调影响,所以我们可以从最左端往右,最右端往左更新取最小值(也就题目描述可能复杂一些)
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=110,M=3e5+10;
#define PII pair<int,int>
int n,k;
int a[M];
int b[M];
void solve(){
cin>>n>>k;
int minn=1000000;
int maxn=0;
// 初始化
memset(b,0x3f,sizeof b);
for(int i=1;i<=k;i++) {
cin >> a[i];
minn=min(minn,a[i]);
maxn=max(maxn,a[i]);
}
//状态1⃣️
for(int i=1;i<=k;i++){
cin>>b[a[i]];
}
//状态2⃣️从前往后依次遍历
for(int i=minn+1;i<=n;i++){
b[i]=min(b[i],b[i-1]+1);
}
//状态3⃣️从后往前更新状态
for(int i=maxn-1;i>=1;i--){
b[i]=min(b[i],b[i+1]+1);
}
for(int i=1;i<=n;i++) cout<<b[i]<<" ";
cout<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin>>t;
while (t--) {
solve();
}
return 0;
}
gBrutality - CodeForces 1107C - Virtual Judge
思路:连续字母区间取最前k大的值就好
代码:
#include <bits/stdc++.h>
#define int long long
#define PII pair<int,int>
using namespace std;
int n,k;
int a[200010];
bool cmp(int x,int y){
return x>y;
}
void solve()
{
cin>>n>>k;
int res=0;
for(int i=0;i<n;i++) cin>>a[i];
string s;
cin>>s;
for(int i=0;i<n;){
int b[200010];
int j=i;
int tt=0;
while(s[j]==s[i]&&j<n){
b[tt++]=a[j];
j++;
}
sort(b,b+tt,cmp);
int cnt=0;
// cout<<tt<<endl;
for(int l=0;l<tt;l++){
// cout<<b[l]<<" ";
if(cnt>=k) break;
res+=b[l];
cnt++;
}
i=j;
}
cout<<res<<endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin>>t;
while (t--) {
solve();
}
return 0;
}
*hAll Your Paths are Different Lengths - AtCoder arc102_b - Virtual Judge
思路:那年我双手插兜,不知道该往哪里走
*iConstrained Nim 2 - AtCoder abc297_g - Virtual Judge
思路:太难了,放过鼠鼠吧。