HDU - 6983 7017
原题:
题意:将一段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; }
原题:
题意:当区间长度>=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; }

浙公网安备 33010602011771号