2017.08.15总结
来源:互联网 发布:领啦试用网站源码 编辑:程序博客网 时间:2024/06/07 03:19
题意:
在给定序列中求出一个区间,最小值是左边界,最大值是右边界。求最大区间长度。
思路:
存下最大值与最小值,然后枚举区间左边界,再用二分法找出满足“最小值是左边界”这个条件的最大区间的右边界编号,然后在这个区间里求出最大值,就是要求的区间了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 50050
#define maxn 100050
int a[N];
int index[maxn];
int dpmax[N][20];
int dpmin[N][20];
void makemax(int n)
{
for(int i=0; i<n; i++)
dpmax[i][0]=a[i];
for(int j=1; (1<<j)<=n; j++)
{
for(int i=0; i+(1<<j)-1<=n; i++)
{
dpmax[i][j]=max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]);
}
}
}
void makemin(int n)
{
for(int i=0; i<n; i++)
dpmin[i][0]=a[i];
for(int j=1; (1<<j)<=n; j++)
{
for(int i=0; i+(1<<j)-1<=n; i++)
{
dpmin[i][j]=min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]);
}
}
}
int getmax(int l,int r)
{
int k=(int)(log(r-l+1.0)/log(2.0));
if(dpmax[l][k]>dpmax[r-(1<<k)+1][k])
return index[dpmax[l][k]];
else
return index[dpmax[r-(1<<k)+1][k]];
}
int getmin(int l,int r)
{
int k=(int)(log(r-l+1.0)/log(2.0));
if(dpmin[l][k]>dpmin[r-(1<<k)+1][k])
return index[dpmin[r-(1<<k)+1][k]];
else
return index[dpmin[l][k]];
}
int finds(int l,int r)
{
int mid;
int s=l;
int t=r;
while(s<t)
{
mid=(s+t)>>1;
if(getmin(l,mid)==l)
s=mid+1;
else
t=mid-1;
}
return t;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(dpmax,0,sizeof(dpmax));
memset(dpmin,0,sizeof(dpmin));
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
index[a[i]]=i;
}
makemax(n);
makemin(n);
int m=0;
int s,t;
for(int i=0; i<n-1; i++)
{
s=finds(i,n-1);
t=getmax(i,s);
if(t-i>m)
m=t-i;
}
if(m==0)
printf("-1\n");
else
printf("%d\n",m);
}
return 0;
}
练习赛第六题:
递推.
一、当n为奇数时,a[n]=a[n-1];
二、当n为偶数时有两种情况:
1、n=n-2+1+1;
2、n=n/2*2;
所以:a[n]=a[n-2]+a[n/2];
#include<stdio.h>
int a[1000010];
void fun()
{
int i;
a[1]=1;
a[2]=2;
for(i=3;i<=1000010;i++)
{
if(i&1)
a[i]=a[i-1]%1000000000;
else
a[i]=(a[i-2]+a[i/2])%1000000000;
}
}
int main()
{
int n;
fun();
while(scanf("%d",&n)!=EOF)
{
printf("%d\n",a[n]);
}
}
第一题:
题意:
你的角色从2出发,到3终止,但你要拿到一个4 给3,其中1不能走,0是可以走的路,问最短路的长度是多少?
思路:
两次bfs,分别求出2到4的距离和3到4的距离,求两个距离相加的最小值。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1e3 + 10;
#define INF 0x3f3f3f3f
int n, m;
int a[maxn][maxn];
int vis[maxn][maxn];
int d1[maxn][maxn];
int d2[maxn][maxn];
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
vector<pair<int, int> > b;
void bfs(int x, int y, int tt[][maxn]){
queue<pair<int, int> > q;
memset(vis, 0, sizeof vis);
q.push(make_pair(x, y));
int cnt = 0;
while(!q.empty()){
pair<int, int> t = q.front(); q.pop();
if(a[t.first][t.second] == 4) cnt++;
if(cnt == b.size()) return;
for(int i = 0; i < 4; i++){
int xx = t.first + dx[i];
int yy = t.second + dy[i];
if(xx < 0 || xx >= n || yy < 0 || yy >= m) continue;
if(a[xx][yy] != 1 && !vis[xx][yy]){
vis[xx][yy] = 1;
tt[xx][yy] = tt[t.first][t.second] + 1;
q.push(make_pair(xx, yy));
}
}
}
}
int main(){
int t1, t2, p1, p2;
scanf("%d%d", &m, &n);
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
scanf("%d", &a[i][j]);
if(a[i][j] == 3){
t1 = i;
t2 = j;
}
if(a[i][j] == 2){
p1 = i;
p2 = j;
}
if(a[i][j] == 4){
b.push_back(make_pair(i, j));
}
}
int minn = INF;
memset(d1, 0, sizeof d1);
memset(d2, 0, sizeof d2);
bfs(p1, p2, d1);
bfs(t1, t2, d2);
for(int i = 0; i < b.size(); i++){
int ss = b[i].first, pp = b[i].second;
if(d1[ss][pp] && d2[ss][pp])
minn = min(minn, d1[ss][pp] + d2[ss][pp]);
}
printf("%d\n", minn);
}
- 2017.08.15总结
- 总结15
- 2017.08.04总结
- 2017.08.05总结
- 2017.08.14总结
- 2017.08.16总结
- 2017.08.17总结
- 2017.08.18总结
- 2017.08.19总结
- 2017.08.21总结
- 2017.08.23总结
- 总结—2014.03.15
- 每日总结-05-15
- 第15周总结
- 2014.6.15总结
- 2014.08.15 总结
- 2014.10.15面试总结
- 2014.10.15学习总结
- junit5相关依赖的写法
- Leaf Classification
- sklearn中文api翻译
- 各种排序算法的积累
- ServiceWorker
- 2017.08.15总结
- 写给自己的Java程序员学习路线图
- Oracle
- Sticks题解
- IIC && SPI架构浅析
- JAVA基础:“==”和“equals”的区别
- Perlin noise(三)
- jQuery click事件多次触发
- Hdu 6129 Just do it【杨辉三角、规律】