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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> HDU6964 I love counting (字典树+莫队) -> 正文阅读

[数据结构与算法]HDU6964 I love counting (字典树+莫队)

题意:
给定一个长度为 n n n 的序列 c , q c,q cq 次询问,每次给出 l , r , a , b l,r,a,b l,r,a,b求在 [ l , r ] [l,r] [l,r]中有多少种不同的值 k k k 满足 k ⊕ a ≤ b ? . k⊕a≤b?. kab?.

题解:
莫队+字典树
补题的时候看到了带佬新得一种写法,即把字典树当成一颗完全二叉树去跑,不需要新建结点编号。

在 Trie 上顺着 a⊕b 走 ,为什么要跟着a⊕b走呢?
因为顺着a⊕b走也就是,顺着a⊕字典树=b走 当b=1时,就可以把c⊕a=0加入答案
若 b 当前位是 1,则所有 k⊕a 在当前位是 0 的数字都符合要求
找出字典树中与a当前为相同得值 (让其⊕后为0)

当然树状数组上套一个字典树也是一个不错得选择,先对r进行排序,然后离线询问,老套路题了。

代码:

#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include<bits/stdc++.h>

using namespace std;
const int maxn=1e5+10;


struct Q{
    int l,r,k,a,b;
}pp[maxn];
int n,m,k;
int pos[maxn],a[maxn],cnt[maxn];
int sum[maxn*18],ans[maxn];
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return x*f;
}

struct rule{
    bool operator()(const Q & a,const Q & b)const{
    if(pos[a.l]!=pos[b.l]) return a.l<b.l;
    if(pos[a.l]&1) return a.r<b.r;
    return a.r>b.r;
    }
};

void add(int x,int v){
    int node=1;
    sum[node]+=v;
    for(int i=17;i>=0;i--){
        node=(node<<1)+(x>>i&1);
        sum[node]+=v;
    }
}

int query(int a,int b){
    int node=1,res=0;
    //cout<<"debug"<<endl;
    for(int i=17;i>=0;i--){  
    //在 Trie 上贴着 a^b 走  也就是说贴着a^字典树=b走 当b=1时,就可以把k^a=0加入答案
        int t=(a>>i&1)^(b>>i&1);
    //若 b 当前位是 1,则所有 k^a 在当前位是 0 的数字都符合要求
        if(b>>i&1) res+=sum[(node<<1)+(t^1)];
   //找出字典树中与a当前为相同得值 (让其^后为0)
        node=(node<<1)+t;
    }
    res+=sum[node];
    return res;
}


int main() {
//    ios::sync_with_stdio(false);
//    cin.tie(0);
//    cout.tie(0);

    n=read();
    int sz=sqrt(n);
    for(int i=1;i<=n;i++){
        a[i]=read();
        pos[i]=i/sz;
    }
    int q;
    q=read();
    for(int i=1;i<=q;i++){
        pp[i].l=read();
        pp[i].r=read();
        pp[i].a=read();
        pp[i].b=read();
        pp[i].k=i;
    }
    sort(pp+1,pp+1+q,rule());
    int l=1,r=0;
    for(int i=1;i<=q;i++){
        while(pp[i].l<l){
            l--;
            if(++cnt[a[l]]==1){
                add(a[l],1);
            }
        }
        while(pp[i].r>r){
            r++;
            if(++cnt[a[r]]==1){
                add(a[r],1);
            }
        }
        while(pp[i].l>l){
            if(--cnt[a[l]]==0){
                add(a[l],-1);
            }
            l++;
        }
        while(pp[i].r<r){
            if(--cnt[a[r]]==0){
                add(a[r],-1);
            }
            r--;
        }
        ans[pp[i].k]=query(pp[i].a,pp[i].b);
    }
    for(int i=1;i<=q;i++){
        printf("%d\n",ans[i]);
    }
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:53:22  更:2021-07-31 16:54:04 
 
开发: 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/25 16:30:04-

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