IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明)M(可持久化权值线段树+思维暴力) -> 正文阅读

[数据结构与算法]第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明)M(可持久化权值线段树+思维暴力)

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明)M(可持久化权值线段树+思维暴力)

题意简述:

n n n堆石子, R i k a Rika Rika S a t o k o Satoko Satoko两人根据这 n n n堆石子玩一个游戏, R i k a Rika Rika在这 n n n堆石子里面选择连续的几堆石子,然后要求 S a t o k o Satoko Satoko写下一个数量,如果这个数量 R i k a Rika Rika无法用这连续几堆石子任意组成的话 (子序列) 那么 R i k a Rika Rika胜利,否则 S a t o k o Satoko Satoko胜利,求 S a t o k o Satoko Satoko写下的最小的数使得其胜利。那么这题就转化成了MEX问题。求这连续的几堆石子所有构造数的MEX是什么。

思维部分:

首先设 S n = A [ 1 ] + A [ 2 ] + A [ 3 ] + . . . + A [ n ] Sn=A[1]+A[2]+A[3]+...+A[n] Sn=A[1]+A[2]+A[3]+...+A[n],使得 X n = S n + 1 Xn=Sn+1 Xn=Sn+1 A [ 1 ] A[1] A[1] ~ A [ n ] A[n] A[n]是从小到大的互不相同的数( A [ i ] A[i] A[i]的数量不局限于 1 1 1)。假使 A [ 1 ] A[1] A[1] ~ A [ n ] A[n] A[n]可以构造出 1 1 1 ~ S n Sn Sn中任意一个数,那么如果 A [ n + 1 ] > A[n+1]> A[n+1]> X n Xn Xn那么答案即是 X n Xn Xn因为后面的数全部大于 X n Xn Xn,必然无法构成 X n Xn Xn。否则求出 S n + 1 = A [ 1 ] + A [ 2 ] + A [ 3 ] + . . . + A [ n ] + A [ n + 1 ] Sn+1=A[1]+A[2]+A[3]+...+A[n]+A[n+1] Sn+1=A[1]+A[2]+A[3]+...+A[n]+A[n+1],同样 A [ 1 ] A[1] A[1] ~ A [ n + 1 ] A[n+1] A[n+1]可以构成 1 1 1 ~ S [ n + 1 ] S[n+1] S[n+1]内任意的数,继续往下求直至发现无法构成的数

算法部分:

显然,要求从小到大的互不相同数时,我们可以想到的是可持久化权值线段树来维护数大小之间的相对关系。和经典主席树入门题:第K小数 有着相同的维护操作,只是将第K小数中维护的每个数出现次数变成了下标从 0 0 0到所求下标 x x x之内所有数的和,所以我们改为维护每个下标值的 s u m sum sum,即出现次数 ? * ? 下标数本身大小。剩余相对较难部分我认为即暴力求出最小的构造不了的数。时间复杂度是 O ( l o g n ) O(logn) O(logn),因为每次的判断是一个倍增的过程。

  • 实现代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long//谨慎使用,这题是因为内存给的很大
int n,q;
const int N = 1e6+10;
int a[N];
int root[N];//可持久化的历史状态的根节点
vector<int>vec;
int cnt;
struct Node{
    int l,r;
    int sum;//sum维护每个idx上数的总和
}tr[N*4+N*21];//N*4+NlogN
int build(int l,int r){//第K小数的板子
    int p=++cnt;
    if(l==r)return p;
    int mid=l+r>>1;
    tr[p].l=build(l,mid);
    tr[p].r=build(mid+1,r);
    return p;
}
int find(int x){//二分
    return lower_bound(vec.begin(),vec.end(),x)-vec.begin();
}
int insert(int pre,int l,int r,int x){//也类似于第K小数板子
    int p=++cnt;
    tr[p]=tr[pre];//指向上一个状态 
    if(l==r){
        tr[p].sum+=vec[x];
        return p;
    }
    int mid=l+r>>1;
    if(x<=mid)tr[p].l=insert(tr[p].l,l,mid,x);
    else tr[p].r=insert(tr[p].r,mid+1,r,x);
    tr[p].sum=tr[tr[p].l].sum+tr[tr[p].r].sum;
    return p;
} 
int query(int pre,int now,int l,int r,int x){//相对于第K小数变动一点,因为此处要求的前缀值
    if(r<=x)return tr[now].sum-tr[pre].sum;
    int mid=l+r>>1;
    if(x<=mid)return query(tr[pre].l,tr[now].l,l,mid,x);
    else return  query(tr[pre].l,tr[now].l,l,mid,mid)+query(tr[pre].r,tr[now].r,mid+1,r,x);
} 
signed main(){
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        vec.push_back(a[i]);
    }
    sort(vec.begin(),vec.end());
    vec.erase(unique(vec.begin(),vec.end()),vec.end());//离散化 
    root[0]=build(0,vec.size()-1);
    for(int i=1;i<=n;i++){
        root[i]=insert(root[i-1],0,vec.size()-1,find(a[i]));//在0~n-1的范围内在find(a[i])上插入 
    }
    int ans=0;
    while(q--){
        int l,r;
        cin>>l>>r;
        int l1,r1;
        l1=(l+ans)%n+1;
        r1=(r+ans)%n+1;
        l=min(l1,r1);
        r=max(l1,r1);
        ans=0;
        int pre=-1;//如果没有1的话第一次x是-1直接返回,有1存在x是0。
        while(1){
            int x=upper_bound(vec.begin(),vec.end(),ans+1)-vec.begin();//找第一个大于ans+1的下标
            x--;
            if(x==pre)break;
            ans=query(root[l-1],root[r],0,vec.size()-1,x);//更新ans为最大值,同时消除l-1的影响 
            pre=x;
        }
        ans++;
        cout<<ans<<endl;
    }
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:24:47  更:2022-04-15 00:28:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:42:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码