周结3 2021-07-31

King of Range
链接
题目大意:给定的一个区间内,最小值与最大值,要严格大于题目给出的k,问这样的区间有几个

思路:比赛的时候,一开始暴力,但会tle,后面用指针,然后用map存储最大最小,但是仍旧超时,方法是可以用模拟队列,一个维护最大一个最小,类似滑动窗口,可以输出结果。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,k;
ll a[100005];
ll v[100005],qmax[100005],qmin[100005];	//一个维护最大,一个维护最小
void solve(){
    scanf("%lld %lld",&n,&m);
    for (int i = 1; i <= n; ++i)
        scanf("%lld",&a[i]);
    while(m--){
        ll ans=0,tmp=1;
        ll head1=1,tail1=0;
        ll head2=1,tail2=0;
        scanf("%lld",&k);
        for(int i=1;i<=n;i++){
            while(head1<=tail1&&a[i]>=a[qmax[tail1]]) tail1--;	//对入队出队用tail来操作
            qmax[++tail1]=i;
            while(head2<=tail2&&a[i]<=a[qmin[tail2]]) tail2--;
            qmin[++tail2]=i;
            while(head1<=tail1&&head2<=tail2&&a[qmax[head1]]-a[qmin[head2]]>k){
                ans+=n-i+1;
                tmp++;
                if(qmax[head1]<tmp) head1++;
                if(qmin[head2]<tmp) head2++;
            }
        }
        printf("%lld\n",ans);
    }
}
int main(){
    solve();
}

Querying Multiset
链接
这道题还是一道简单的题,不过stl用的不熟练,没有写完,思路也很简单,就是一道模拟题,输入1,2,3,分别对应了三种操作,按照要求操作就可以。

思路用小根堆存储,每次出队头即可

#include<bits/stdc++.h>
 
using namespace std;
 
typedef long long int LLD;
 
int main()
{
    int q;
    LLD sum = 0;
    priority_queue<LLD, vector<LLD>, greater<LLD> >pq;	//优先队列,小根堆
 
    scanf("%d", &q);
 
    for (int i = 0; i<q; i++)
    {
        LLD tmp_q, x;
        scanf("%lld", &tmp_q);
 
        if (tmp_q == 1)
        {
            scanf("%lld", &x);
            pq.push(x - sum);
        } else if (tmp_q == 2) {
            scanf("%lld", &x);
            sum += x;
        } else {
            x = pq.top();
            printf("%lld\n", (x + sum));
            pq.pop();
        }
        
    }
    
 
    return 0;
}

Boxes
链接
震惊三观。。。。。。。题目说有n个盒子,每个盒子里面有一个黑球或者白球,我们要知道每个盒子里是什么球,需要最少的花费是多少,其中一种操作是直接花费wi开一个盒,另一种操作是花费c,来得知剩下的盒子里有多少黑球。

思路:迭代的思想,先对w数组排序,每次开盒开最小的一个,之后的开盒代价为代价为c+sumwi(1-1/(2^(n-1))

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

//int w[N];
double w[N];
int main()
{
//    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    int n;
    double c;
    cin >> n >> c;
    double sum = 0, ans = 0;
    for (int i = 1; i <= n; i ++ ) scanf("%lf", &w[i]), sum += w[i];
    sort(w + 1, w + n + 1);
    for (int i = 1; i <= n; i ++ ) ans = ans / 2 + w[i];
    printf("%.8lf\n", min(sum, sum - ans + c));
    return 0;
}

Math
链接
题目大意就是要我们给出一个对,使得xy+1|x^2 +y^2成立,就是前面那个可以整除后面那个式子

就是一道打表的问题,但是要考虑时间超时的问题,要找到i^3<=n来优化。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;

ll a[10000005];
int main() {
    int T;
    long long n;
    long long N = 1e18;
    cin >> T;
    int ln = 0;
    for (long long i = 2; 1ll * i * i * i <= N; i++) {
        long long x = i, y = i * i * i;
        while (y <= N) {
            a[++ln] = y;
            if ((N + x) / i / i < y) break; //不满足条件,break
            long long tmp = y * i * i - x;
            x = y;
            y = tmp;
        }
    }                           //通过规律不断更新(x,y),并记录下y值
    sort(a + 1, a + ln + 1);    //由于存入的y每个k不同,需排序
    while (T--) {
        cin >> n;
        int x = upper_bound(a + 1, a + ln + 1, n) - a;    //二分查找,返回个数
        cout<<x<<endl;
    }
}

Scholomance Academy
链接

这道题题意真的非常难以理解,它的大意是有一个值thita,把它当做0,比它大的都为正,比它小的都为负,题目每次会给你两个量,一个量是+,-表示猜测值,和一个具体数值,要你根据thita来判断它是正是负,以此来得出4个量,再又4个量,来计算出一个值,然后在图中得出一个点,根据thita的变动,我们可以得出一个图,再得出这个曲线的积分也就是面积。

数据量是1e6,我们想的就是,模拟这些数,来得出这个图的转折点在哪,因为这个图一定是一些横着的线组成的。

#include<bits/stdc++.h>
using namespace std;
vector<int>a,b;
int main()
{
    int n;
    cin >> n;
    for(int i=1;i<=n;i++)
    {
        char c;
        int x;
        cin >> c >> x;
        if(c=='+')
            a.push_back(x);
        else
            b.push_back(x);
    }
    sort(a.begin(),a.end());
    sort(b.begin(),b.end());
    double ans=0;
    for(auto i:b)
        ans=ans+a.end()-upper_bound(a.begin(),a.end(),i);
    printf("%.10lf\n",ans/(a.size()*b.size()));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值