2019湖北省赛网络赛C Store CDQ分治

本文详细解析了2019湖北省赛网络赛中的一道题目,该题目涉及商店销售记录的管理。题目要求根据特定的操作类型查询产品信息,通过CDQ分治策略解决二维偏序问题。文章介绍了CDQ分治的思想,如何维护递增序列,并使用集合(set)处理查询操作,同时给出了复杂度分析和AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ichuan is a store owner and his store has n products, numbered from 1 to ?.

Recently, his business is not very good, and he can occasionally sell a product, so he will confirm the information of the products sold.

???,it means that on the ??ℎ day, the product numbered ? is sold.

???,in currently sold products, those whose number is greater than or equal to ?, which one is the lowest number which sold before the ??ℎ day (including ??ℎ day) .

Input
the first line contains two positive integers ?,?(2≤?,?≤200000),which are the number of products and operations.

The following Q lines, each line contains one operator character (? or ?) and two integers ?,?.(1≤?≤109,1≤?≤?)

Output
For each request of type ???,output the number of required product. If no such product exists, output −1.
Examples
input

3 4
M 10 3
M 5 1
D 20 2
D 5 1

output

3
1

input

10 10
M 20 10
D 1 9
M 2 3
D 17 10
M 20 2
D 8 2
M 40 1
D 25 2
M 33 9
D 37 9

output

-1
-1
3
2
9

感觉这个题意写的不是很明确,感感觉改成在每次操作M后第x天发现了一笔y的订单,然后D操作是查询已经发现的订单中订购时间在第x天之前的编号大于等于y的最小编号。

题意感觉就是个二维偏序问题,因此cdq分治可做。

cdq分治的过程中我们维护x为递增序列,然后用set维护y,每次为W操作的时候加入set,D操作的时候更新答案。

复杂度: O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
struct node{
    int op,x,y,id;
    node(){}
    node(int op,int x,int y,int id):x(x),y(y),op(op),id(id){}
    bool operator<(const node n1)const{
        return x<n1.x||(x==n1.x&&op<n1.op); 
    }
}p[N],tmp[N];
int ans[N];
set<int>ss;
void cdq(int l,int r){
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    cdq(l,mid);
    cdq(mid+1,r);
    int s=l,t=mid+1,o=0; 
    while(s<=mid&&t<=r){
        if(p[s]<p[t]){
            if(p[s].op==1){
                ss.insert(p[s].y);
            }
            tmp[o++]=p[s++];
        }
        else{
            if(p[t].op==2){
                auto it=ss.lower_bound(p[t].y);
                if(it!=ss.end()){
                    ans[p[t].id]=min(*it,ans[p[t].id]);
                }
            }
            tmp[o++]=p[t++];
        }
    }
    while(s<=mid){
		tmp[o++]=p[s++];
	}
	while(t<=r){
		if(p[t].op==2){
            auto it=ss.lower_bound(p[t].y);
           // if(l==1&&r==4)
                
            if(it!=ss.end()){
                ans[p[t].id]=min(*it,ans[p[t].id]);
            }
        }
        tmp[o++]=p[t++];
    }
    for(int i=0;i<o;i++){
        p[l+i]=tmp[i];
    }
    ss.clear();
}
int main(){
    int n,q,x,y;
    char a[N];
    scanf("%d%d",&n,&q);
    for(int i=1;i<=q;i++){
        scanf("%s%d%d",a,&x,&y);
        p[i]=node(a[0]=='M'?1:2,x,y,i);
        if(a[0]=='D'){
            ans[i]=inf;
        }
    }
    cdq(1,q);
    for(int i=1;i<=q;i++){
        if(ans[i]>0){
            if(ans[i]==inf)
                printf("-1\n");
            else
                printf("%d\n",ans[i]);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值