16.7.15
2016-07-15 10:37
239 查看
gcd递归求最大公约数
RMQ区间最值查询(ST算法)(转载)
RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。对于该问题,最容易想到的解决方案是遍历,复杂度是O(n)。但当数据量非常大且查询很频繁时,该算法无法在有效的时间内查询出正解。
比较高效的算法是在线算法(ST算法)。所谓在线算法,是指用户每输入一个查询便马上处理一个查询。该算法一般用较长的时间做预处理,待信息充足以后便可以用较少的时间回答每个查询。ST(Sparse Table)算法是一个非常有名的在线处理RMQ问题的算法,它可以在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。
首先DP预处理
设A[i]是要求区间最值的数列,F[i, j]表示从第i个数起连续2^j个数中的最大值。(DP的状态)
例如 A数列为:3 2 4 5 6 8 1 2 9 7
F[1,1] = max(3,2) = 3, F[1,2]=max(3,2,4,5) = 5,F[1,3] = max(3,2,4,5,6,8,1,2) = 8;
并且我们可以容易的看出F[i,0]就等于A[i]。(DP的初始值)
大区间可划分为左右两块小区间,状态转移方程为F[i, j]=max(F[i,j-1], F[i + 2^(j-1),j-1])。
状态转移方程的含义是:先更新所有长度为F[i,0]即1个元素,然后通过2个1个元素的最值,获得所有长度为F[i,1]即2个元素的最值,然后再通过2个2个元素的最值,获得所有长度为F[i,2]即4个元素的最值,以此类推更新所有长度的最值。
然后查询
假如我们需要查询的区间为(i,j),那么我们需要找到覆盖这个闭区间(左边界取i,右边界取j)的最小幂(可以重复,比如查询5,6,7,8,9,我们可以查询5678和6789)。
因为这个区间的长度为j - i + 1,所以我们可以取k=log2( j - i + 1),则有:RMQ(A, i, j)=max{F[i , k], F[ j - 2 ^ k + 1, k]}。
//—————
//今日代码
2016-07-15 personal training
A
B
E
H
int gcd(int a,int b) { if(a>=b) return a%b==0?b:gcd(b,a%b); else return gcd(b,a); }
RMQ区间最值查询(ST算法)(转载)
RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。对于该问题,最容易想到的解决方案是遍历,复杂度是O(n)。但当数据量非常大且查询很频繁时,该算法无法在有效的时间内查询出正解。
比较高效的算法是在线算法(ST算法)。所谓在线算法,是指用户每输入一个查询便马上处理一个查询。该算法一般用较长的时间做预处理,待信息充足以后便可以用较少的时间回答每个查询。ST(Sparse Table)算法是一个非常有名的在线处理RMQ问题的算法,它可以在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。
首先DP预处理
设A[i]是要求区间最值的数列,F[i, j]表示从第i个数起连续2^j个数中的最大值。(DP的状态)
例如 A数列为:3 2 4 5 6 8 1 2 9 7
F[1,1] = max(3,2) = 3, F[1,2]=max(3,2,4,5) = 5,F[1,3] = max(3,2,4,5,6,8,1,2) = 8;
并且我们可以容易的看出F[i,0]就等于A[i]。(DP的初始值)
大区间可划分为左右两块小区间,状态转移方程为F[i, j]=max(F[i,j-1], F[i + 2^(j-1),j-1])。
状态转移方程的含义是:先更新所有长度为F[i,0]即1个元素,然后通过2个1个元素的最值,获得所有长度为F[i,1]即2个元素的最值,然后再通过2个2个元素的最值,获得所有长度为F[i,2]即4个元素的最值,以此类推更新所有长度的最值。
void RMQ(int num) //预处理->O(nlogn) { for(int j = 1; j < 20; ++j) for(int i = 1; i <= num; ++i) if(i + (1 << j) - 1 <= num) { maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]); minsum[i][j] = min(minsum[i][j - 1], minsum[i + (1 << (j - 1))][j - 1]); } }
然后查询
假如我们需要查询的区间为(i,j),那么我们需要找到覆盖这个闭区间(左边界取i,右边界取j)的最小幂(可以重复,比如查询5,6,7,8,9,我们可以查询5678和6789)。
因为这个区间的长度为j - i + 1,所以我们可以取k=log2( j - i + 1),则有:RMQ(A, i, j)=max{F[i , k], F[ j - 2 ^ k + 1, k]}。
//—————
//今日代码
2016-07-15 personal training
A
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<cmath> using namespace std; int main() { freopen("xx.in","r",stdin); freopen("xx.out","w",stdout); double l,p,q; cin >> l >> p >> q; double time = l/(p+q); double len = p*time; cout << len << endl; return 0; }
B
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<cmath> using namespace std; int arr[500050]; int main() { freopen("xx.in","r",stdin); freopen("xx.out","w",stdout); int n; cin >> n; for(int i = 0; i < n; i++) scanf("%d",&arr[i]); int step = 0; int L,R; int l,r; for(int i = 0; i < n-1; i++) { L = i,R = i; while(arr[R]!=arr[R+1] && R < n-1) R++; l = L+1,r = R-1; int s = 0; while(l<=r) { s++; arr[l] = arr[L]; arr[r] = arr[R]; l++; r--; } if(step<s) step = s; } cout << step<< endl; cout << arr[0]; for(int i = 1; i < n; i++) printf(" %d",arr[i]); cout << endl; return 0; }
E
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<cmath> #define LL long long using namespace std; LL mypow(double a,int b) { LL r = 1; LL base = a; while(b!=0) { if(b&1) r*=base; base*=base; b>>=1; } return r; } int main() { freopen("xx.in","r",stdin); freopen("xx.out","w",stdout); double n,X; double m,Y; cin >> n >> X; double num; LL ans1 = 0; LL ans2 = 0; for(int i = 0; i < n; i++) { cin >> num; ans1+= num*mypow(X,n-i-1); } cin >> m >> Y; for(int i = 0; i < m ; i++) { cin >> num; ans2+= num*mypow(Y,m-i-1); } // cout << ans1 <<endl<< ans2<<endl; if(ans1==ans2) cout <<"=" << endl; else if(ans1 > ans2) cout << ">" << endl; else cout <<"<"<<endl; return 0; }
H
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<cmath> #define LL long long using namespace std; int arr[10086]; int main() { freopen("xx.in","r",stdin); freopen("xx.out","w",stdout); for(int i = 1; i <=26; i++) arr[i] = i; int n,m; cin >> n >> m; string s; cin >> s; char c1,c2; for(int i = 0;i < m; i++) { cin >> c1 >> c2; for(int j = 1; j <= 26; j++) { if(arr[j] == c1-'a'+1) arr[j] = c2-'a'+1; else if(arr[j] == c2-'a'+1) arr[j] = c1-'a'+1; } } for(int i = 0; i < n; i++) cout << (char)(arr[s[i]-'a'+1]+'a'-1); cout << endl; return 0; }
相关文章推荐
- Android自动文本框输入识别提示功能代码
- C语言提高总结
- 【Proto文件】Google开源技术 Protobuf 简介与使用
- java入门第一季_1.4_java中的常用标识符
- 使用TCP/IP的套接字(Socket)进行通信
- 多线程任务Callable与Future或FutureTask的使用
- ArcGIS空间参考
- java学习笔记八:static关键字
- 一个sample学会使用epoll
- java解析任意层的json数据(递归解析)
- java中添加按钮并添加响应事件
- BaseService --- service层的抽取
- 5. Longest Palindromic Substring
- poj 3040 Allowance
- EasyUI常用组件(基础)
- Exception in thread “main” java.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop
- has leaked window com.android.internal.policy.impl.PhoneWindow$ that was originally added here
- EasyUI常用组件(基础)
- EasyUI常用组件(基础)
- iOS UILabel:宽度固定,自动高度显示全部文字