CF #271 div2
2014-10-07 18:33:08
思路:6题场,真激情~因为unrated,水过D就滚粗了QAQ。A、B、C没搞,听说C是个裸暴力,卡long long 0.0。
D:不多说了,dp转移方程:dp[i] = dp[i - 1] + dp[i - k]
E:离散化后用线段树维护一个DP,因为有输出路径的存在而变得巨坑。。。先将所有高度离散化,然后根据离散化后的数组建树,节点存的是这个高度区间内的最大dp值。在dp的时候,设考虑dp[i],那么在线段树中查询[1,hi - d] , [hi + d,tree_size]内的最大值,算出dp[i]后更新线段树,因为dp值是一个一个加入树中的,所以比较方便。要注意的是在记录路径的时候是记录离该点最近的max(dp[j]) (j < i),所以位置映射数组要即使更新!(见97行),被这个坑地RE到死啊QAQ。
1 /************************************************************************* 2 > File Name: e.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 07 Oct 2014 01:05:56 AM CST 6 ************************************************************************/ 7 #include <cstdio> 8 #include <cstring> 9 #include <cstdlib> 10 #include <cmath> 11 #include <vector> 12 #include <map> 13 #include <set> 14 #include <queue> 15 #include <iostream> 16 #include <algorithm> 17 using namespace std; 18 #define lp (p << 1) 19 #define rp (p << 1|1) 20 #define getmid(l,r) (l + (r - l) / 2) 21 #define MP(a,b) make_pair(a,b) 22 typedef long long ll; 23 const int INF = 1 << 30; 24 const int maxn = 100010; 25 26 int n,pa[maxn],ah[maxn],pre,ansmax; 27 ll h[maxn],bh[maxn],d; 28 29 struct node{ 30 int tmax,id; 31 }t[maxn << 2]; 32 33 void Query_max(int a,int b,int p,int l,int r){ 34 if(a <= l && r <= b){ 35 if(t[p].tmax > ansmax){ 36 ansmax = t[p].tmax; 37 pre = t[p].id; 38 } 39 return; 40 } 41 int mid = getmid(l,r); 42 if(a <= mid) Query_max(a,b,lp,l,mid); 43 if(b > mid) Query_max(a,b,rp,mid + 1,r); 44 } 45 46 void Update(int a,int v,int p,int l,int r){ 47 if(l == r){ 48 t[p].tmax = v; 49 return; 50 } 51 int mid = getmid(l,r); 52 if(a <= mid) Update(a,v,lp,l,mid); 53 else Update(a,v,rp,mid + 1,r); 54 t[p].tmax = max(t[lp].tmax,t[rp].tmax); 55 if(t[p].tmax == t[lp].tmax) t[p].id = t[lp].id; 56 else t[p].id = t[rp].id; 57 } 58 59 void Build_tree(int p,int l,int r){ 60 t[p].tmax = 0; 61 if(l == r){ 62 t[p].id = l; 63 return; 64 } 65 int mid = getmid(l,r); 66 Build_tree(lp,l,mid); 67 Build_tree(rp,mid + 1,r); 68 } 69 70 void Print(int p){ 71 if(pa[p] == 0){ 72 printf("%d",p); 73 return; 74 } 75 if(pa[p]) Print(pa[p]); 76 printf(" %d",p); 77 } 78 79 int main(){ 80 scanf("%d%I64d",&n,&d); 81 for(int i = 1; i <= n; ++i){ 82 scanf("%I64d",h + i); 83 bh[i] = h[i]; 84 } 85 sort(bh + 1,bh + (ll)n + 1); 86 int sz = unique(bh + 1,bh + (ll)n + 1) - bh - 1; 87 Build_tree(1,1,sz); 88 for(int i = 1; i <= n; ++i){ 89 int l = upper_bound(bh + 1,bh + (ll)sz + 1,h[i] - d) - bh; 90 int r = lower_bound(bh + 1,bh + (ll)sz + 1,h[i] + d) - bh; 91 ansmax = -1; 92 if(r <= sz) Query_max(r,sz,1,1,sz); 93 if(1 <= l - 1) Query_max(1,l - 1,1,1,sz); 94 int pos = lower_bound(bh + 1,bh + (ll)sz + 1,h[i]) - bh; 95 Update(pos,ansmax + 1,1,1,sz); 96 pa[i] = ah[pre]; 97 ah[pos] = i; 98 } 99 printf("%d\n",t[1].tmax); 100 Print(ah[t[1].id]); 101 puts(""); 102 return 0; 103 }
F:这题反而比E简单,用线段树维护区间内所有数的gcd值,发现区间内满足条件的情况只可能是区间gcd == 区间最小值,答案就是区间长度 - 最小值个数。所以开两棵线段树,一棵维护区间gcd值,一棵区间最小值及其个数。
1 By suda1327405059, contest: Codeforces Round #271 (Div. 2), problem: (F) Ant colony, Accepted, # 2 /************************************************************************* 3 > File Name: f.cpp 4 > Author: Nature 5 > Mail: 564374850@qq.com 6 > Created Time: Tue 07 Oct 2014 01:45:42 AM CST 7 ************************************************************************/ 8 9 #include <cstdio> 10 #include <cstring> 11 #include <cstdlib> 12 #include <cmath> 13 #include <vector> 14 #include <map> 15 #include <set> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 100010; 27 28 int Gcd(int a,int b){ return b == 0 ? a : Gcd(b,a % b);} 29 30 int n,q; 31 int s[maxn]; 32 struct node{ 33 int num; 34 int g,tmin; 35 }t[maxn << 2]; 36 37 void Build_tree(int p,int l,int r){ 38 t[p].num = 0; 39 if(l == r){ 40 t[p].g = t[p].tmin = s[l]; 41 t[p].num = 1; 42 return; 43 } 44 int mid = getmid(l,r); 45 Build_tree(lp,l,mid); 46 Build_tree(rp,mid + 1,r); 47 t[p].g = Gcd(t[lp].g,t[rp].g); 48 t[p].tmin = min(t[lp].tmin,t[rp].tmin); 49 if(t[p].tmin == t[lp].tmin) t[p].num += t[lp].num; 50 if(t[p].tmin == t[rp].tmin) t[p].num += t[rp].num; 51 } 52 53 int Query_min(int a,int b,int v,int p,int l,int r){ 54 if(a <= l && r <= b){ 55 if(t[p].tmin == v) return t[p].num; 56 else return 0; 57 } 58 int mid = getmid(l,r),res = 0; 59 if(a <= mid) res += Query_min(a,b,v,lp,l,mid); 60 if(b > mid) res += Query_min(a,b,v,rp,mid + 1,r); 61 return res; 62 } 63 64 int Query_gcd(int a,int b,int p,int l,int r){ 65 if(a <= l && r <= b) 66 return t[p].g; 67 int res = -1,mid = getmid(l,r); 68 if(a <= mid) res = Query_gcd(a,b,lp,l,mid); 69 if(b > mid){ 70 if(res == -1) res = Query_gcd(a,b,rp,mid + 1,r); 71 else res = Gcd(res,Query_gcd(a,b,rp,mid + 1,r)); 72 } 73 return res; 74 } 75 76 int Find(int a,int b){ 77 int G = Query_gcd(a,b,1,1,n); 78 return Query_min(a,b,G,1,1,n); 79 } 80 81 int main(){ 82 int a,b; 83 scanf("%d",&n); 84 for(int i = 1; i <= n; ++i) 85 scanf("%d",s + i); 86 Build_tree(1,1,n); 87 scanf("%d",&q); 88 for(int i = 1; i <= q; ++i){ 89 scanf("%d%d",&a,&b); 90 printf("%d\n",b - a + 1 - Find(a,b)); 91 } 92 return 0; 93 }