CSP模测

A : TT 的袜子

题目描述

TT 有一屋子的袜子,总共有
n
n 只,袜子有
k
k 种颜色,每天 TT 都要穿两只颜色相同的袜子,这一天结束后 TT 会丢弃今天的袜子。

现在输入所有袜子的颜色,输出 TT 的袜子可以坚持用多少天。

输入描述

第一行输入
n
,
k
n,k (
1

n
,
k

1000
1≤n,k≤1000)。
第二行输入
n
n 个数,第
i
i 个数
c
i
c
i

表示第
i
i 只袜子的颜色(
1

c
i

k
1≤c
i

≤k)。

输出描述

输出一个数,表示答案。

输入样例

10 5
1 2 1 3 1 5 4 4 2 2
输出样例

3

#include<iostream>

#include<vector>

#include<algorithm>

using namespace std;

int main()

{

vector<int> vtr;

int n,k;

cin>>n>>k;

int num;

for(int l=0;l<n;l++)

{cin>>num;vtr.push_back(num);}

sort(vtr.begin(),vtr.end());

 

int i=0;

int j=1;

int ans=0;

while(j<n)

{

	

if(vtr[i]==vtr[j])

{	ans++;

	i+=2;

	j+=2;

}

 

else

{i++,j++;

}

}

cout<<ans<<endl;

} 

在这里插入图片描述

B : 定价

题目描述


n
n 个人买东西同一个商品,第
i
i 个人认为合理的价格区间
[
l
i
,
r
i
]
[l
i

,r
i

],表示如果价格低于
l
l 嫌便宜,如果价格高于
r
r 嫌贵。

请你设计商品的价格,使在满足尽可能多的人认为价格合理的条件下,商品价格最高。具体来说,你需要输出最终商品的定价与认为价格合理的人数。

输入描述

第一行输入一个整数
n
(
1

n

1
0
6
)
n(1≤n≤10
6
),表示人数。
接下来
n
n 行,第
i
i 行输入两个数
l
i
,
r
i
l
i

,r
i

(
1

l
i

r
i

1
0
6
)
(1≤l
i

≤r
i

≤10
6
),表示第
i
i 个人认为的价格合理的区间。

输出描述

输出一行两个整数,以一个空格分割,分别表示最终商品的定价与认为价格合理的人数。

输入样例

5
1 3
2 4
2 3
3 4
4 5
输出样例

3 4
子任务

存在
70
%
70% 的测试数据,
n

1000

,


i
,
l
i

r
i

1000
n≤1000 , ∀i,l
i

≤r
i

≤1000

对于所有的测试数据,
1

n

1
0
6
1≤n≤10
6


i
,
1

l
i

r
i

1
0
6
∀i,1≤l
i ≤r i ≤10 6

#include <iostream>
#include <map>

using std::pair;
using std::map;

int main()
{
    int n;
    map<int, int> areas;
    pair<int, int> *ps;
    scanf("%d", &n);
    ps = new pair<int, int>[n];

    for (int i = 0; i < n; i++)
    {
        int l, r;
        scanf("%d %d", &l, &r);
        ps[i].first = l;
        ps[i].second = r;
        areas.insert(pair<int, int>(l, 0));
        areas.insert(pair<int, int>(r, 0));
    }

    for (int i = 0; i < n; i++)
    {
        areas.find(ps[i].first)->second += 1;
        map<int, int>::iterator end = areas.find(ps[i].second);
        end++;
        if (end != areas.end())
            end->second -= 1;
    }

    int p = 0;
    int c = 0;
    int mc = 0;
    for (map<int, int>::iterator it = areas.begin(); it != areas.end(); it++)
    {
        mc += it->second;
        if (mc >= c)
        {
            c = mc;
            p = it->first;
        }
    }

    printf("%d %d\n", p, c);

}

在这里插入图片描述

C : 吃包子

问题描述

来来来,尝尝新出炉的包子啊!

L
L 和小
W
W 买了
n
n 个包子排成一行,用
s
i
s
i

表示第
i
i 个包子的大小,并且包子大小最大值是
x
x。

W
W 是个挑剔的人,小
W
W 只肯按照包子大小不递减的顺序吃包子。
现在小
L
L 会负责吃掉大小
s
i
s
i

处在
[
l
,
r
]
[l,r] 范围内的所有的包子,之后小
W
W 会按照包子标号从小到大依次吃掉剩下的包子,如果剩下的包子没有满足不递减的顺序,小
W
W 会不肯吃。
现在小
L
L 想知道有多少种
[
l
,
r
]
[l,r] 的方案可以让小
W
W 肯吃包子。
一个合法的
[
l
,
r
]
[l,r] ,
l
l 和
r
r 必须都是
1

l

r

x
1≤l≤r≤x 的整数

输入格式

第一行一个整数
n
,
x
n,x ,表示有
n
n 个包子,包子的最大大小为
x
x。
1

n
,
x

1
0
6
1≤n,x≤10
6

接下来一行,有
n
n 个数,第
i
i 个数
s
i
s
i

表示第
i
i 个包子的大小。
1

s
i

x
1≤s
i

≤x

输出格式

输出一行,一个整数表示方案数。

样例输入

5 4
1 3 2 4 2
样例输出

7
样例解释

[
1
,
2
]
[1,2] : 去掉数值处在范围
[
1
,
2
]
[1,2] 的数值之后,剩余数列为
{
3
,
4
}
{3,4} ,是非递减数列
[
1
,
3
]
[1,3] : 去掉数值处在范围
[
1
,
3
]
[1,3] 的数值之后,剩余数列为
{
4
}
{4} ,是非递减数列
[
1
,
4
]
[1,4] : 去掉数值处在范围
[
1
,
4
]
[1,4] 的数值之后,剩余数列为
{
}
{} ,是非递减数列
[
2
,
2
]
[2,2] : 去掉数值处在范围
[
2
,
2
]
[2,2] 的数值之后,剩余数列为
{
1
,
3
,
4
}
{1,3,4} ,是非递减数列
[
2
,
3
]
[2,3] : 去掉数值处在范围
[
2
,
3
]
[2,3] 的数值之后,剩余数列为
{
1
,
4
}
{1,4} ,是非递减数列
[
2
,
4
]
[2,4] : 去掉数值处在范围
[
2
,
4
]
[2,4] 的数值之后,剩余数列为
{
1
}
{1} ,是非递减数列
[
3
,
4
]
[3,4] : 去掉数值处在范围
[
3
,
4
]
[3,4] 的数值之后,剩余数列为
{
1
,
2
,
2
}
{1,2,2} ,是非递减数列
共有
7
7 种方案。

数据范围

对于
30
%
30% 的数据,满足
1

n
,
x

500
1≤n,x≤500
对于
80
%
80% 的数据,满足
1

n
,
x

5000
1≤n,x≤5000
对于
100
%
100% 的数据,满足
1

n
,
x

1
0
6
1≤n,x≤10
6

#include <bits/stdc++.h>
using namespace std;
const long long N = 1000010;
void in(long long &x){
    cin>>x;
}
void o(long long x){
    cout<<x;
}
long long n,x;
long long cnt;//逆序数量
long long a[N],dp[N];//包子,最小的右端点
set<long long>st;//当前数组
vector<long long>g[N];//  g[i]中包含重量为i的所有的包子的位置
void Add(long long x){//  把大小为x的包子加入数组中
    for(long long i=0;i<g[x].size();i++){
        auto it = st.lower_bound(g[x][i]);
        long long last=-1,next = -1;
        if(it!=st.end())next=*(it);
        if(it!=st.begin())it--,last=*(it);
        if(next!=-1&&last!=-1){
            if(a[next]<a[last])cnt--;
            if(x<a[last])cnt++;
            if(a[next]<x)cnt++;
        }else if(next!=-1){
            if(a[next]<x)cnt++;
        }else if(last!=-1){
            if(x<a[last])cnt++;
        }
        st.insert(g[x][i]);
    }
}
void Drop(long long x){//  将大小为x的包子从数组中删去
    for(long long i=0;i<g[x].size();i++){
        auto it = st.lower_bound(g[x][i]);
        long long next = -1,last = -1;
        it++;if(it!=st.end())next = *(it);
        it--;
        if(it!=st.begin()){
            it--;
            last = *(it);
            it++;
        }
        if(last!=-1){
            if(a[last]>x)cnt--;
        }
        if(next!=-1){
            if(a[next]<x)cnt--;
        }
        if(next!=-1&&last!=-1){
            if(a[next]<a[last])cnt++;
        }
        st.erase(g[x][i]);
    }
}
bool check(){
    return cnt==0;
}
signed main(){
    in(n);in(x);
    for(long long i=1;i<=n;i++){
        in(a[i]);
        g[a[i]].push_back(i);//将下标i加入到g[a[i]]中
    }
    for(long long i=1;i<=x;i++)Add(i);//  把所有包子加进去
    long long r = 1;
    for(long long  i=1;i<=x;i++){
        Add(i-1);//左端点i加了1,删除重量为i-1的包子
        if(r==i){//特判一下,右端点不能等于左端点
            Drop(r);//删掉r
            r++;
        }
        while(!check()){
            if(r==x+2)break;//没有有r与i对应了,退出循环
            Drop(r);r++;//删掉r
        }
        dp[i]=r-1;//记录答案
    }
    long long ans=0;//统计答案
    for(long long i=1;i<=x;i++){
        ans+=(x-dp[i]+1);
    }
    o(ans);
    putchar('\n');
    return 0;
}

在这里插入图片描述

思路

TT的袜子
统计某种颜色的袜子个数;
天数=每种颜色袜子个数/2 求和。

第二题
将区间边界转换成点,对所有点进行排序,扫描排序结果。当遇到起点时,重叠个数加一,并且记录重叠个数的最大值;当遇到止点时,重叠个数减一。

吃包子在这俩基础上得加一些东西,
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值