牛客多校五

King of Range

牛客多校五
题意
题目是让我们找到一段序列中所有的区间,满足区间最大值和区间最小值的差大于k
题解
这道题我们可以用单调队列和st表解决
st表,直接爆搜整个区间,找到区间内最短的满足的长度,相加就好了
单调队列
对于单调队列,我们可以用两个单调队列一个单增一个单减,单增的队列维护最小值,但减的序列维护最大值,然后弹出最前面的,找到离我们当前区间最近的满足的,逐个计算,由于首位置不同不会重复
注意是要弹出找到最近的满足的;

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int maxx[N], minn[N], a[N];
int n, m, k;
long long ans;
void solve() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++)cin >> a[i];
	while (m--) {
		int mil = 1, mxl = 1, mir = 0, mxr = 0;
		cin >> k;
		ans = 0;
		for (int i = 1,last=0; i <= n; i++) {
			while (mil <= mir && a[minn[mir]] >= a[i])mir--;
			minn[++mir] = i; 
			while (mxl <= mxr && a[maxx[mxr]] <= a[i])mxr--;
			maxx[++mxr] = i;
			while (mil <= mir && mxl <= mxr && a[maxx[mxl]] - a[minn[mil]] > k) {
				if (mil <= mir && (mxl > mxr || minn[mil] < maxx[mxr]))last = minn[mil++];
				else last = maxx[mxl++];
			}
			ans += last;
		}
		cout << ans << endl;
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin.exceptions(ios::badbit | ios::failbit);
	solve();
}

Boxes

牛客多校五
比较简单的高中数学算概率的问题吧,对于每一种我们只需要求一次hint就知道有多少个黑球多少个白球了。
比较全开和一次hint开的情况,求出最小的那个

#include<vector>
#include<string>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cmath>
using namespace std;
//#define _ 0
//return ~~(0^_^0)~~
int n;
const int maxn = 1e5 + 5;
long double a[maxn];
long double c;
void solve() {
	cin >> n >> c;
	long double a1, a2;
	a1 = a2 = 0.0;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		a1 = a1 + 1.0 * a[i];
	}
	a2 = a2 + c;
	sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; i++) {
		a2 += a[i] * (1.0 - 1.0 / pow(2, n - i));
	}
	cout<<fixed<<setprecision(6)<<min(a1, a2);
}
signed main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	solve();
}

Double String

dp问题还是等补了dp来补吧(哎)

Holding Two

牛客多校五
题意
要求我们构造一个n行m列的矩阵,其中要求每一行每一列每一条对角线上都不能有连续三个字符相同
题解
由题意我们可以想到一个简单的构造,讲0和1两个两个的排再一起,行和列都这样构造,那么一定不可能出现连续三个相同的情况
如3 3 就是
1 1 0
0 0 1
1 1 0
这样是不会出现连续三个相同的情况的;

#include<iostream>
#include<vector>
#include<string>
using namespace std;
void solve() {
    int n, m;
    cin >> n >> m;
    vector<string>a(n);
    
    for (int i = 0; i < n; i++) {
        int  flag = 0;
        if (i % 2 == 0) {
            for (int j = 0; j < m; j += 2) {
                flag++;
                if (flag % 2 == 0)a[i] += "00";
                else a[i] += "11";
            }
        }
        else {
            for (int j = 0; j < m; j += 2) {
                flag++;
                if (flag % 2 == 0)a[i] += "11";
                else a[i] += "00";
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cout << a[i][j];
        }
        cout << endl;
    }
}
int main() {
    solve();
}

Jewels

牛客多校五
题意
题目的意思是求最小消耗的精力
在三维平面上有一些宝物,这些宝物会随时间以各自的v的速度往下掉,捡起这个宝物的代价是它和我们距离的平方
由此我们可以建立一个时间宝物的二部图,每个图的边权就是所需要的代价,找出它的最优匹配,最优匹配中所有权值的和就是我们要求的代价。
(嫖到板子了真开心)

#include<vector>
#include<string>
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
//#define _ 0
//return ~~(0^_^0)~~
#define ll long long
const int N=407,NPOS=-1;
const ll INF=1ll<<60;
struct Matrix
{
    int n;
    ll a[N][N];
};
struct KuhnMunkres:Matrix
{
    ll hl[N],hr[N],slk[N];
    int fl[N],fr[N],vl[N],vr[N],pre[N],q[N],ql,qr;
    int check(int i)
    {
        if(vl[i]=1,fl[i]!=NPOS)return vr[q[qr++]=fl[i]]=1;
        while(i!=NPOS)swap(i,fr[fl[i]=pre[i]]);
        return 0;
    }
    void bfs(int s)
    {
        fill(slk,slk+n,INF),fill(vl,vl+n,0),fill(vr,vr+n,0);
        for(vr[q[ql=0]=s]=qr=1;;)
        {
            for(ll d; ql<qr;)
                for(int i=0,j=q[ql++]; i<n; ++i)
                    if(!vl[i]&&slk[i]>=(d=hl[i]+hr[j]-a[i][j]))
                        if(pre[i]=j,d)slk[i]=d;
                        else if(!check(i))return;
            ll d=INF;
            for(int i=0; i<n; ++i)
                if(!vl[i]&&d>slk[i])d=slk[i];
            for(int i=0; i<n; ++i)
            {
                if(vl[i])hl[i]+=d;
                else slk[i]-=d;
                if(vr[i])hr[i]-=d;
            }
            for(int i=0; i<n; ++i)
                if(!vl[i]&&!slk[i]&&!check(i))return;
        }
    }
    void ask()
    {
        fill(fl,fl+n,NPOS),fill(fr,fr+n,NPOS),fill(hr,hr+n,0);
        for(int i=0; i<n; ++i)hl[i]=*max_element(a[i],a[i]+n);
        for(int j=0; j<n; ++j)bfs(j);
    }
} km;
 
int n;
ll ans;
void solve() {
    cin>>n;
    for (int i=0;i<n;i++) {
        int x,y,z,v;
        cin>>x>>y>>z>>v;
        ans+=x*x+y*y;
        for (int j=0;j<n;j++) km.a[i][j]=(1ll<<50)-(ll)(z+v*j)*(z+v*j);
    }
    km.n=n;
    km.ask();
    for (int i=0;i<n;i++) ans+=(1ll<<50)-km.a[i][km.fl[i]];
    cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	solve();
}
上一篇:1318:【例5.3】自然数的拆分


下一篇:Educational Codeforces Round 112 (Rated for Div. 2)