2020.1.8学习

‎字典树的学习真的很麻烦,线段也是
关于数组优化运用的示例

#include<bits/stdc++.h>
using namespace std;
#define maxn 100007  //元素总个数
int a[maxn],n;//存原数组下标[1,n]

void init (int n){for(int i = 1; i<=n;i++)a[i]=0;}
int main()
{
    while(~scanf("%d", &n)!=EOF)
    {
        if(n==0)break;
        init(n);
        for(int i = 1; i <= n; i++)
        {
            int l,r;
            cin>>l>>r;
            a[l]++;
            a[r+1]--;
        }
        for(int i = 1; i <= n; i++)
        {
            if(i==1)printf("%d", a[1]);
            else
            {
                a[i]+=a[i-1];
                printf(" %d", a[i]);
            }
        }
        cout<<endl;
    }
    return 0;
}
/*1 4
  1 0 0 0 1
  1 1 1 1 1*/

学习理解中

#include <bits/stdc++.h>
using namespace std;
int fa[105];
int  find(int n)
{
    if(fa[n]==n) return n;
    else return fa[n]=find(fa[n]);
}
struct Node{
    int x,y;
}node[105];
bool check(Node a,Node b)
{
    if(a.x==b.x) return 1;
    else if(a.y==b.y)return 1;
    else return 0;
}
set<int> cnt;
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        fa[i]=i;
        cin>>node[i].x>>node[i].y;
        for(int j=0;j<i;j++)
        {
            if(check(node[i],node[j])){

                fa[find(j)]=find(i);
               // cout<<fa[j]<<endl;
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        //cout<<find(fa[i])<<endl;
        cnt.insert(find(i));
    }
    cout<<cnt.size()-1<<endl;
}

及离散化树状数组

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=500005;
int a[maxn],c[maxn];
int n;
struct org
{
    int v, f;
}b[maxn];
int cmp(org a,org b)
{
    return a.v<b.v;
}
int lowbit(int i)
{
    return i&(-i);
}
int update(int i,int x)
{
    while(i<=maxn)
    {
        c[i]=c[i]+x;
        i=i+lowbit(i);
    }
    //cout<<"1"<<endl;
}
int query(int i)
{
    int sum=0;
    while(i>0)
{
        sum+=c[i];
        i=i-lowbit(i);
 
    }
 
    return sum;
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&b[i].v);
            b[i].f=i;
        }
        sort(b+1,b+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            a[b[i].f]=i;
        }
        long long  sum=0;
        for(int i=1;i<=n;i++)
        {
            update(a[i],1);
            sum+=i-query(a[i]);
        }
        cout<<sum<<endl;
    }
    return 0;
}

以下为大纲内容

树状数组 支持的操作 快速求前缀和 O(logn)O(logn) 修改某一个数 O(logn)O(logn) 对比 求前缀和 修改 数组储存
O(n)O(n) O(1)O(1) 维护前缀和数组 O(1)O(1) O(n)O(n) 基本原理 二进制 \large
x=2{i_k}+2{i_{k-1}}+2{i_{k-2}}+…+2{i_1}x=2 i k ​ +2 i k−1
​ +2 i k−2 ​ +…+2 i 1 ​
 v_k\leq v_{k-1}\leq v_{k-2}\leq…\leq v_{1}v k ​ ≤v k−1 ​ ≤v k−2 ​ ≤…≤v 1 ​ ,kk是递减的,所以有 k\leq log_2xk≤log 2 ​ x 求 00~xx
区间的数之和可以按如下方案分解  \large (x-2^{i_1 },x](x−2 i 1 ​ ,x]  \large
2^{i_1}2 i 1 ​
个数,2^{i_1}2 i 1 ​
是 xx 的二进制表示的最后一个11  \large (x-2{i_1}-2{i_2},x-2^{i_1}](x−2 i 1 ​ −2 i 2 ​ ,x−2 i 1 ​ ]  \large 2^{i_2}2 i 2 ​
个数,2^{i_2}2 i 2 ​
是 x-2^{i_1}x−2 i 1 ​
的二进制表示的最后一个11 ……  \large (0,x-2{i_1}-2{i_2}-…-2^{k-1}](0,x−2 i 1 ​ −2 i 2 ​ −…−2 k−1 ]  \large 2^{i_k}2 i k ​
个数 如何维护这每一个区间和呢?观察区间数的性质 区间 (L,R](L,R] 的长度一定是 RR 的二进制表示的最后一个 11 所对应的二次幂  (L,R]=[R-lowbit®+1,R](L,R]=[R−lowbit®+1,R] , lobit(x)=x
&(-x)lobit(x)=x&(−x) ,用 c[R]c[R] 表示  11~nn 个数,最多只会有 nn 个区间,因为由右端点唯一确定
 c[x]=a[x-lowbit(x)+1,x]c[x]=a[x−lowbit(x)+1,x] ,以 xx 为右端点,区间所有数之和 对于
x=…100…0x=…100…0 有 kk 个零,c[x]=以x结尾的,长度是2^k的区间之和c[x]=以x结尾的,长度是2 k
的区间之和 儿子的形式0…01…10…0 把儿子累加起来
 c[x]=ax+c{x-1}+c{x-1-lowbit(x-1)}c[x]=ax+cx−1+cx−1−lowbit(x−1)
直到0为止,麻烦 父节点找子节点 子节点找父节点,修改操作 找到所有包含 xx 的 假设 pp 是父节点 …10…0…10…0
它的所有子节点…01…10…0…01…10…0 从11开始kk位,逆向上一步
加上0000000000000010…00000000000000010…0 直接影响的区间是唯一的
 p=x+lowbit(x)p=x+lowbit(x) 迭代直接影响的区间,没走一次末尾0加一,logxlogx次
for(i=x;i<=n;i+=lobit(i) tr[i]+=c; 查询 11~xx: for(i=x;i;i-=lobit(i))
tr[i]-=c; 扩展 和差分结合 和差分结合配合公式 线段树 pushup由子节点计算父节点信息 pushdown由父节点下传到子节点
操作 pushup build 将区间初始化为线段树 modify 修改 单点修改 区间修改 pushdown query 查询 二叉树
数组模拟链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值