首页 > 其他分享 >近段时间出现可以用multiset解决的题目

近段时间出现可以用multiset解决的题目

时间:2023-08-27 13:57:07浏览次数:32  
标签:insert 题目 res 段时间 up multiset it2 find it1

近段时间出现可以用multiset解决的题目

AtCoder Beginner Contest 308 G Minimum Xor Pair Query

题意:有一个数组进行 \(3\) 种操作:

  1. 加一个数
  2. 删一个数
  3. 打印数组 \(\min _{ 1 \leq i < j \leq n} {a_i \bigoplus a_j}\)

结论:拍序后的数组,其最小异或对在相邻两数中产生

那么我们就需要维护一个数的多重集合,一个异或值的多重集合

在每次插入时 例如 \(x, y\) -> \(x , y, z\) 在异或值的多重集合中删除 \(x \bigoplus z\) ,插入入 \(x \bigoplus y\) , \(y \bigoplus z\)

同理删除时\(x, y, z\) -> \(x, z\) 在异或值的多重集合删除 \(x \bigoplus y\) , \(y \bigoplus z\) 插入 \(x \bigoplus z\)

打印就输出异或值的多重集合的最小值即可

// LUOGU_RID: 117557481
//  AC one more times

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int mod = 1e9 + 7;
const int N = 2e5 + 10;
const ll up = 1 << 30;
multiset<ll> s, res;
int q;

void add(ll x)
{
    s.insert(x);
    multiset<ll>::iterator it1 = s.find(x), it2 = s.find(x);
    it1--, it2++;
    if(*it1 != -1 && *it2 != up) 
        res.erase(res.find((*it1) ^ (*it2)));
    if(*it1 != -1)
        res.insert(x ^ (*it1));
    if(*it2 != up)
        res.insert(x ^ (*it2));
    //cout<<x<<'\n';
}

void del(ll x)
{
    multiset<ll>::iterator it1 = s.find(x), it2 = s.find(x);
    it1--, it2++;
    if(*it1 != -1 && *it2 != up) 
        res.insert((*it1) ^ (*it2));
    if(*it1 != -1)
        res.erase(res.find((*it1) ^ x));
    if(*it2 != up)
        res.erase(res.find(x ^ (*it2)));
    s.erase(s.find(x));
}

void solve()
{       
    cin>>q;
    s.insert(-1);   s.insert(up);
    for(int i = 1; i <= q; i++)
    {
        int opt;    cin>>opt;
        if(opt == 3)
        {
            cout<<*res.begin()<<'\n';
        }
        else
        {
            ll x;  cin>>x;
            if(opt == 1)
                add(x);
            else if(opt == 2)
                del(x);
        }
    }
    return;
}
  
int main()
{
    std::ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    
    int TC = 1;
    
    //cin >> TC;    
    for(int tc = 1; tc <= TC; tc++)
    {
        //cout << "Case #" << tc << ": ";         
        solve();
    }


    return 0;
}

G - The Great Equalizer

找了个规律,\(res = \text{排序后数组中最大的差} + \text{数组中最大的元素}\)

怎么处理这个问题呢,用multiset处理一下,最近cf,atc都出过两次可以用同样方法解决的题目了,先去吃个饭,待补

update:每次操作使得排序后数组中相邻两数的差减少 \(1\) ,数组中的最大值又会增加 \(1\) ,所以 \(res = \text{排序后数组中最大的差} + \text{数组中最大的元素}\)

//  AC one more times

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int mod = 1e9 + 7;
const int N = 2e5 + 10;
const ll up = 1ll << 60;
ll n, q, a[N];  
multiset<ll> s, res;
void add(ll x)
{
    s.insert(x);
    multiset<ll>::iterator it1 = s.find(x), it2 = s.find(x);
    it1--, it2++;
    if(*it1 != -1 && *it2 != up) 
        res.erase(res.find((*it2) - (*it1)));
    if(*it1 != -1)
        res.insert(x - (*it1));
    if(*it2 != up)
        res.insert((*it2) - x);
    //cout<<x<<'\n';
}

void del(ll x)
{
    multiset<ll>::iterator it1 = s.find(x), it2 = s.find(x);
    it1--, it2++;
    if(*it1 != -1 && *it2 != up) 
        res.insert((*it2) - (*it1));
    if(*it1 != -1)
        res.erase(res.find(x - (*it1)));
    if(*it2 != up)
        res.erase(res.find((*it2) - x));
    s.erase(s.find(x));
}
void solve()
{       
    cin>>n;
    res.clear();    s.clear();
    s.insert(-1);   s.insert(up);
    for(int i = 1; i <= n; i++)
    {
        cin>>a[i];
        add(a[i]);
    }
    cin>>q;
    for(int i = 1; i <= q; i++)
    {
        ll p, x;   cin>>p>>x;
        del(a[p]);  a[p] = x; add(a[p]);
        if(n == 1)
        {
            cout<<a[n]<<" ";
            continue;
        }
        cout<<*(--(--s.end())) + *(--res.end())<<" ";
    }
    cout<<'\n';
    return;
}

标签:insert,题目,res,段时间,up,multiset,it2,find,it1
From: https://www.cnblogs.com/magicat/p/17660205.html

相关文章

  • Java限制某段时间内某个请求的次数(代码库)
    关键就是统计次数技巧:1、使用guavacache缓存来计数2、利用引用变量的特性,减少put,只使用get如果重新put赋值,缓存的时间会刷新,比如下面例子的b,一共输出了7次,而a只输出了5次importcom.google.common.cache.Cache;publicclassTest2{privatestaticCache<String,Tes......
  • 1000:入门测试题目
    1000:入门测试题目时间限制:1000ms      内存限制:32768KB提交数:300841   通过数:180737【题目描述】求两个整数的和。【输入】一行,两个用空格隔开的整数。【输出】两个整数的和。【输入样例】23【输出样例】5#include<iostream>intm......
  • 1.C++入门以及简单顺序结构题目
    1.C++入门以及简单顺序结构题目1.交换值【题目描述】输入两个正整数a和b,试交换a、b的值(使a的值等于b,b的值等于a)。【输入】输入两个正整数a和b。【输出】输出a与b交换值后的结果。【输入样例】23【输出样例】32inta=2,b=3,c;cin>>a>>b;c=a;a=b;b=c;cout<<a......
  • C++入门及简单程序结构题目
    C++入门及简单顺序结构题目1.交换值【题目描述】输入两个正整数a和b,试交换a、b的值(使a的值等于b,b的值等于a)。【输入】输入两个正整数a和b。【输出】输出a与b交换值后的结果。【输入样例】23【输出样例】32inta,b,c;cin>>a>>b;c=a;a=b;b=c;printf("%d%d",......
  • 1.C++入门以及简单顺序结构题目
    1.C++入门以及简单顺序结构题目™1.交换值【题目描述】输入两个正整数a和b,试交换a、b的值(使a的值等于b,b的值等于a)。【输入】输入两个正整数a和b。【输出】输出a与b交换值后的结果。【输入样例】23【输出样例】32inta,b;cin>>a>>b;printf("%d%d",b,a);2.整......
  • Java_面试题目冰山一角
    特别说明:这些都是偶然遇到的题目(有些是同僚说到,有些是群里说到,有些是书籍提到,总之就是偶然遇到),没有指导作用,切记!再加上正好有空闲,就贴上来供大家探讨,有什么意见建议也可以直接评论什么的!谢谢大家的光临!1、已知Pi可以用函数4*(1–1/3+1/5–1/7+…)计算,项越多越精确,请写......
  • 资讯_Windows 8笔记本电脑关机后电源灯要亮一段时间,是否正常?
    Windows8笔记本电脑关机后电源灯要亮一段时间,是否正常故障现象:随着Windows8的普及,多次遇到用户反馈安装Windows8的笔记本在执行关机动作后,屏幕关闭之后电源等指示灯还要亮几十秒,甚至几分钟不等。——此现象其实是由于Windows8的混合关机特质所致,并不属于故障的范畴。原因分析:在W......
  • E. Imprecise Computer和华为CCPC2023挑战赛的一道题目
    华为挑战赛建议看我们队长的2023CCPC华为云挑战赛C-装箱问题-凉宫景-博客园(cnblogs.com)Problem-E-Codeforces题目说是有台计算机对于绝对值差小于2的两个数的大小判断会出错误,现在要求对1-n判断两轮小于i的数,然后做差绝对值.给出绝对值序列,问是否是这个计算机......
  • ACM题目 英雄护美(递归)
    /*英雄护美英雄救美,可以理解;英雄护美,亦可理解。m(1<=m<=54)个英雄和美晚上行军,路过大峡谷,只能以纵队的方式前行。为确保美的绝对安全,纵队中每两个美之间必须至少有一个以上的英雄。如m为3时,有5种行军方式,分别为:美-英雄-美、美-英雄-英雄、英雄......
  • ACM题目:孔融分梨
    /*孔融分梨孔融让梨,人人称颂;孔融分梨,也不简单。孔融有M个同样的梨,要分给N个人。每个人手上有一个同样的盘子,孔融要将梨放入盘中,允许有的盘子空着不放,问共有多少种不同的分法?3,1,1和1,3,1和1,1,3是同一种分法。第一行是测试数据的数目t(0<......