CF 1555

CF1555

A:

推公式题,每一个都是 \(2.5\) 的时间,那么我们尽量用 \(10\)

如果是偶数,那么直接可以凑出来,如果是奇数,就 \(+1\) 变成偶数来凑,再考虑特殊情况即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int T,n;
signed main()
{
    cin>>T;
    while(T--){
        cin>>n;
        if(n<6) cout<<15<<endl;
        else cout<<(n+(n%2?1:0))/2*5<<endl; 
    }
    // system("pause");
    return 0;
}

B:

算剩下来的空间左右和上下是否能放下,如果可以,答案就是挪动最少的次数。

枚举最小的情况即可,比较简单。

#include<bits/stdc++.h>
using namespace std;
int T,W,H,X1,Y1,X2,Y2,w,h;
int main()
{
    cin>>T;
    while(T--){
        cin>>W>>H>>X1>>Y1>>X2>>Y2>>w>>h;
        int ans=0x3f3f3f3f,nowx=X2-X1,nowy=Y2-Y1;
        if(w+nowx<=W) ans=min(ans,min(max(0,w-X1),max(0,X2-W+w)));
        if(h+nowy<=H) ans=min(ans,min(max(0,h-Y1),max(0,Y2-H+h)));
        if(ans==0x3f3f3f3f) puts("-1");
        else printf("%.6lf\n",(double)ans);
    }
    // system("pause");
    return 0;
}

C:

可以把题意汇总成一句话:
枚举 \(A\) 在哪里下去,然后 \(B\) 要不直接下去,要不在最后一格才下去

递推即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+1e3;
int T,m;
int a[N],b[N],ans[N],sum1,sum2,answer;
signed main(){
	cin>>T;
	while(T--){
		memset(ans,0,sizeof ans); 
		answer=0x3f3f3f3f,sum1=0,sum2=0;
		//sum1记录在i位置下去时上方红色部分总和
		//sum2记录在i位置下去时下方蓝色部分总和 
		cin>>m;
		for(int i=1;i<=m;i++) cin>>a[i],sum1+=a[i];//提前处理好第一排总和 
		for(int i=1;i<=m;i++){
			cin>>b[i];
			sum1-=a[i];//由上面图可知,红色部分从i+1开始 
			ans[i]=max(sum1,sum2);//取蓝色部分和红色部分中的大值(Bob的聪明) 
			answer=min(ans[i],answer);//取所有蓝色部分和红色部分中的大值中的最小值(Alice的聪明) 
			sum2+=b[i];// 由上面图可知,蓝色部分到i-1结束 
		}
		printf("%lld\n",answer);//最后输出answer,完事 
	}
	return 0;
}

D:

既然只有三个字符,那么回文的情况我们都可以枚举出来。

发现不回文的字符串只能使一个以前三个字符组成的循环,只有 \(6\) 种情况。

对于每次询问,我们枚举这 \(6\) 种方式,取最小值即可。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,sum[7][N];
string s;
void work(char x , char y , char z , int t){
    for(int i = 0; i < n; i++){
        sum[t][i + 1] += sum[t][i];
        if(i % 3 == 0 && s[i] != x) sum[t][i + 1]++;
        if(i % 3 == 1 && s[i] != y) sum[t][i + 1]++;
        if(i % 3 == 2 && s[i] != z) sum[t][i + 1]++;
    }
}

int main(){
    scanf("%d%d",&n,&m);
    cin >> s;
    work('a' , 'b' , 'c' , 1);
    work('b' , 'a' , 'c' , 2);
    work('c' , 'a' , 'b' , 3);
    work('c' , 'b' , 'a' , 4);
    work('a' , 'c' , 'b' , 5);
    work('b' , 'c' , 'a' , 6);
    for(int i = 1,l,r,ans=0x3f3f3f3f; i <= m; i++){
        scanf("%d%d",&l,&r); ans=0x3f3f3f3f;
        for(int j = 1; j <= 6; j++)
            ans = min(ans , sum[j][r] - sum[j][l - 1]);
        printf("%d\n",ans);
    }
    // system("pause");
    return 0;
}

E:

一句话题意:最小化所选线段权值的最大值与最小值之差

我们很显然就可以用双指针做。

双指针的过程中,加入一条线段 \([l,r]\),我们在线段树上将区间 \([l,r−1]\) 加一,删除该线段时就在线段树上将区间 \([l,r−1]\) 减一,判断区间是否被全部覆盖就查询 \([1,m−1]\) 的最小值是否大于零即可。

至于为什么是 \([l,r−1]\),我们可以发现题目要求我们选的线段必须要有重合部分,转化之后就变成将区间 \([1,m−1]\) 覆盖即可,会好做一些。

#include<bits/stdc++.h>
using namespace std;
using namespace std;
inline int read(){
	int x=0; char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+(c^'0'),c=getchar();
	return x;
}
const int N=3e5+10,M=1e6+10;
struct Node{
	int l,r,val,tag;
}t[M*4];
inline void pushup(int x){
	t[x].val=min(t[x<<1].val,t[x<<1|1].val);
}
inline void pushdown(int x){
	if(t[x].tag){
		t[x<<1].val+=t[x].tag,t[x<<1].tag+=t[x].tag;
		t[x<<1|1].val+=t[x].tag,t[x<<1|1].tag+=t[x].tag;
		t[x].tag=0;
	}
}
void build(int x,int l,int r){
	t[x].l=l,t[x].r=r,t[x].val=t[x].tag=0;
	if(l==r) return;
	int mid=l+r>>1;
	build(x<<1,l,mid),build(x<<1|1,mid+1,r); 
}
void modify(int x,int l,int r,int v){
	if(l<=t[x].l&&r>=t[x].r){
		t[x].val+=v,t[x].tag+=v;
		return;
	}
	pushdown(x);
	int mid=t[x].l+t[x].r>>1;
	if(l<=mid) modify(x<<1,l,r,v);
	if(r>mid) modify(x<<1|1,l,r,v);
	pushup(x);
}
int n,m;
struct Segment{
	int l,r,w;
	bool operator<(const Segment &x)const{
		return w<x.w;
	}
}s[N];
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++) s[i].l=read(),s[i].r=read()-1,s[i].w=read();
	sort(s+1,s+n+1);
	build(1,1,m-1);
	int ans=0x3f3f3f3f;
	for(int l=1,r=0;l<=n;l++){
		while(!t[1].val){
			if(++r>n){
				printf("%d\n",ans);
                // system("pause");
				return 0;
			}
			modify(1,s[r].l,s[r].r,1);
		}
		ans=min(ans,s[r].w-s[l].w);
		modify(1,s[l].l,s[l].r,-1);
	}
	printf("%d\n",ans);
    // system("pause");
	return 0;
}
posted @ 2021-08-26 20:00  Evitagen  阅读(51)  评论(0)    收藏  举报