【Codeforces Round #397】Codeforces 765F Souvenirs【解法二】
2017-06-01 21:42
357 查看
解法一(线段树)见这里。
我们维护一棵线段树,树上每个结点用平衡树维护含有的元素,并且维护这个区间中的一个值和这个区间右边的另一个值的差的最小值。按区间的左端点从右往左扫描,每次用ai对区间(i,n]进行覆盖,询问的时候直接询问区间(l,r]最小值。
覆盖的时候一般来说需要递归到底,但是这样复杂度还不如暴力。一个重要的剪枝是维护之前已经遍历的区间的前缀最小值【因为递归的过程本来就是前缀实现的】,如果当前区间没有比这个值更优的解,就不再修改,直接返回。
不难发现线段树套平衡树也可以用主席树实现。
我们维护一棵线段树,树上每个结点用平衡树维护含有的元素,并且维护这个区间中的一个值和这个区间右边的另一个值的差的最小值。按区间的左端点从右往左扫描,每次用ai对区间(i,n]进行覆盖,询问的时候直接询问区间(l,r]最小值。
覆盖的时候一般来说需要递归到底,但是这样复杂度还不如暴力。一个重要的剪枝是维护之前已经遍历的区间的前缀最小值【因为递归的过程本来就是前缀实现的】,如果当前区间没有比这个值更优的解,就不再修改,直接返回。
不难发现线段树套平衡树也可以用主席树实现。
#include<cstdio> #include<algorithm> #include<set> #include<vector> using namespace std; const int maxn=2000010,oo=0x3f3f3f3f; int rd() { int x=0; char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x; } set<int> s[maxn]; vector<int> qry[maxn],v[maxn]; int mn[maxn],a[maxn],l[maxn],r[maxn],ans[maxn], n,q; void build(int u,int L,int R) { mn[u]=oo; for (int i=L;i<=R;i++) s[u].insert(a[i]); if (L==R) return; int mid=(L+R)>>1; build(u<<1,L,mid); build(u<<1|1,mid+1,R); } int query(int u,int L,int R,int l,int r) { if (l<=L&&R<=r) return mn[u]; int mid=(L+R)>>1; int ret=oo; if (l<=mid) ret=min(ret,query(u<<1,L,mid,l,r)); if (r>mid) ret=min(ret,query(u<<1|1,mid+1,R,l,r)); return ret; } void modify(int u,int L,int R,int l,int r,int x,int &res) { set<int>::iterator i1=s[u].lower_bound(x),i2; if (i1!=s[u].begin()) { i2=i1; i2--; } if ((i1==s[u].end()||*i1-x>=res)&&(i1==s[u].begin()||x-*i2>=res)) { res=min(res,query(u,L,R,l,r)); return; } /*if (l<=L&&R<=r) { if (i1!=s.end()) mn[u]=min(mn[u],*it-x); if (i1!=s.begin()) mu[u]=min(mn[u],x-*it); v[u].push_back(x); }*/ if (L==R) { mn[u]=min(mn[u],abs(a[L]-x)); res=min(res,mn[u]); return; } int mid=(L+R)>>1; if (l<=mid) modify(u<<1,L,mid,l,r,x,res); if (r>mid) modify(u<<1|1,mid+1,R,l,r,x,res); mn[u]=min(mn[u<<1],mn[u<<1|1]); } int main() { int res; n=rd(); for (int i=1;i<=n;i++) a[i]=rd(); q=rd(); for (int i=1;i<=q;i++) { l[i]=rd(); r[i]=rd(); qry[l[i]].push_back(i); } build(1,1,n); for (int i=n-1;i;i--) { res=oo; modify(1,1,n,i+1,n,a[i],res); for (vector<int>::iterator it=qry[i].begin();it!=qry[i].end();++it) ans[*it]=query(1,1,n,i+1,r[*it]); } for (int i=1;i<=q;i++) printf("%d\n",ans[i]); }
相关文章推荐
- 【Codeforces Round #397】Codeforces 765F Souvenirs【解法一】
- Codeforces Round #397(Div. 1 + Div. 2 combined)E. Tree Folding【思维+Dfs】dalao们的解法真巧妙系列QAQ
- 【codeforces】Codeforces Round #277.5 (Div. 2)
- Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案 - 动态规划
- Codeforces - Educational Codeforces Round 6C - Pearls in a Row
- Codeforces 584 A. Olesya and Rodion(Codeforces Round #324 (Div. 2))
- 【Codeforces Beta Round #48】 Codeforces 51F Caterpillar
- Codeforces Round #439 (Div. 2) Problem A (Codeforces 869A) - 暴力
- codeforces水题100道 第十九题 Codeforces Round #109 (Div. 2) A. I_love_%username% (brute force)
- codeforces水题100道 第二十七题 Codeforces Round #172 (Div. 2) A. Word Capitalization (strings)
- Codeforces 702 (Educational Codeforces Round 15) A~E
- 【Educational Codeforces Round 16】Codeforces 710A King Moves
- 浅谈Codeforces round 217 Summer Reading的两种解法:DP与构造
- 【Educational Codeforces Round 16】Codeforces 710B Optimal Point on a Line
- Codeforces Beta Round #27 (Codeforces format, Div. 2)
- Codeforces Round #199 (Div. 2) E. Xenia and Tree (非正规解法 分情况dfs)
- Codeforces 584 C. Marina and Vasya (Codeforces Round #324 (Div. 2))
- 【Educational Codeforces Round 16】Codeforces 710C Magic Odd Square
- Codeforces Round #425 (Div. 2) Problem C Strange Radiation (Codeforces 832C) - 二分答案 - 数论
- Codeforces 584 D. Dima and Lisa ( Codeforces Round #324 (Div. 2))