HDU - 6983 7017

原题:Problem - 6983 (hdu.edu.cn)

题意:将一段1~n的区间二分成线段树,当区间的长度r-l+1<=k时,停止二分,统计线段树节点个数。

分析:对区间长度记忆化搜索

题解:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,k;
map<ll,ll> tree;

ll build(ll n)//n表示区间长度
{
    //当tree.find(x)==tree.end()说明原本map中不存在x这个元素
    if(tree.find(n)!=tree.end()) return tree[n];//之前搜过这个长度
    if(n<=k) return tree[n]=1;//区间长度<=k,则该节点为末尾子节点,记节点个数为1
    return tree[n]=build(n/2)+build(n-n/2)+1;//该长度既没搜过,又>k,因此需要递归求得
    //该区间长度覆盖节点个数=二分两边的子区间节点个数+
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&k);
        tree.clear();
        printf("%lld\n",build(n));
    }
    return 0;
}

因为后面有一场和这题做法差不多,所以就一起搬上来啦

原题:Problem - 7017 (hdu.edu.cn)

题意:当区间长度>=3时,三分;长度==2时,二分。

题解:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+5;
ll n;
ll a[N];
map<ll,ll> x;
ll build(ll n)
{
    if(x.find(n)!=x.end()) return x[n];
    if(n==2) return x[n]=3;//区间长度==2,二分后节点数为3
    if(n<=1)return x[n]=1;//末尾子节点,节点数记1
    return x[n]=build(ceil(n/3))+build(floor((ceil(n/3)+n)/2)-ceil(n/3))+build(n-floor((ceil(n/3)+n)/2))+1;//按着给的代码规则硬打
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        x.clear();
        printf("%lld\n",build(n));
    }
    return 0;
}
posted @ 2021-08-06 15:46  AtomsH  阅读(74)  评论(0)    收藏  举报