今天看了看51nod发现有这样一个练习赛,就做了做。因为实力太弱想不出E题,各位神犇勿D。

(5.26UPD:E题想粗来了)

A 区间交

不难发现若干线段[li,ri]的交就是[max(li),min(ri)],那么我们考虑枚举min(ri),将ri>=min(ri)的区间按顺序加入,这时我们显然应该选第k小的li来更新答案。这些操作用个堆就可以轻松维护了。

时间复杂度为O(NlogN)。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int maxn=100010;
int n,k,m;
struct Line {
int l,r;
bool operator < (const Line& ths) const {return r>ths.r;}
}A[maxn];
priority_queue<int> Q;
ll S[maxn];
int main() {
n=read();k=read();m=read();
rep(i,1,n) S[i]=S[i-1]+read();
rep(i,1,m) A[i].l=read(),A[i].r=read();
sort(A+1,A+m+1);
rep(i,1,k) Q.push(A[i].l);
ll ans=max(0ll,S[A[k].r]-S[Q.top()-1]);
rep(i,k+1,m) {
if(Q.top()>A[i].l) Q.pop(),Q.push(A[i].l);
ans=max(ans,S[A[i].r]-S[Q.top()-1]);
}
printf("%lld\n",ans);
return 0;
}

B 中位数计数

开始没有看清题目:“求出每个数在多少个包含其的区间中是中位数”,所以我们只需考虑长度为奇数的区间就可以了。

那么对于每个数x求出答案就是一个经典问题了,<x的Ai设为-1,=x的Ai设为0,>x的Ai设为1,然后求一下有多少区间和为0就可以了。

时间复杂度为O(N^2)。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=8010;
int n,A[maxn],B[maxn],S[maxn*2];
int main() {
n=read();
rep(i,1,n) A[i]=read();
rep(i,1,n) {
rep(j,1,n) {
if(A[i]==A[j]) B[j]=0;
else if(A[i]>A[j]) B[j]=1;
else B[j]=-1;
B[j]+=B[j-1];
}
int ans=0;
memset(S,0,sizeof(S));
for(int j=1;j<=n;j+=2) {
S[B[j-1]+n]++;
ans+=S[B[j]+n];
}
memset(S,0,sizeof(S));
for(int j=2;j<=n;j+=2) {
S[B[j-1]+n]++;
ans+=S[B[j]+n];
}
printf("%d%c",ans,i==n?'\n':' ');
}
return 0;
}

C 瞬间移动

f[i][j]=ΣΣf[i`][j`](i`>=i+1,j`>=j+1)

f[i+1][j]=ΣΣf[i`][j`](i`>i+1,j`>=j+1)

f[i][j+1]=ΣΣf[i`][j`](i`>=i+1,j`>j+1)

f[i][j]=f[i+1][j]+f[i][j+1]-{ΣΣf[i`][j`](i`>i+1,j`>j+1)}+f[i+1][j+1]

=f[i+1][j]+f[i][j+1]

然后坐标变换一下就转化成f[i][j]=f[i-1][j-1]+f[i-1][j]了,答案即为C(n+m-4,n-2)。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int maxn=1010;
const int mod=1000000007;
ll pow(ll n,int m) {ll ans=1;for(;m;m>>=1,(n*=n)%=mod) if(m&1) (ans*=n)%=mod;return ans;}
int f[maxn][maxn];
ll C(int n,int m) {
ll ans1=1,ans2=1;
rep(i,n-m+1,n) (ans1*=i)%=mod;
rep(i,1,m) (ans2*=i)%=mod;
return ans1*pow(ans2,mod-2)%mod;
}
int main() {
int n=read()-1,m=read()-1;
printf("%lld\n",C(n+m-2,n-1));
return 0;
}

D 区间的价值

对随机数据有这样一个性质:如果从位置1向后跳,每次跳到下一个值严格比这一个大的位置,期望跳O(logn)次就会终止。

所以我们可以枚举左端点,模拟右端点的跳跃同时维护当前[l,r]的Ai的最大值mx与最小值mn,用二分套ST表就可以O(logn)计算出下一个mx或mn值改变的位置,在这个区间内答案是不变的,只要在区间打上一个max标记就可以了,用线段树可以做到O(logn),因为总跳越次数为O(nlogn),时间复杂度为O(nlog^2n)。

但这道题有点卡常数,进一步观察得到答案是随长度不增的,所以更新答案时只需要前缀打个标记就行了,这样就可以省掉线段树的常数了。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int maxn=100010;
const int inf=2000000000;
int n,A[maxn];
int Log[maxn],minv[20][maxn],maxv[20][maxn];
void init() {
Log[0]=-1;rep(i,1,n+1) Log[i]=Log[i>>1]+1;
rep(i,1,n) minv[0][i]=maxv[0][i]=A[i];
minv[0][n+1]=-inf;maxv[0][n+1]=inf;
for(int j=1;(1<<j)<=n+1;j++)
for(int i=1;i+(1<<j)<=n+2;i++) {
minv[j][i]=min(minv[j-1][i],minv[j-1][i+(1<<j-1)]);
maxv[j][i]=max(maxv[j-1][i],maxv[j-1][i+(1<<j-1)]);
}
}
int query(int l,int r,int t) {
int k=Log[r-l+1];
if(!t) return min(minv[k][l],minv[k][r-(1<<k)+1]);
return max(maxv[k][l],maxv[k][r-(1<<k)+1]);
}
int getmn(int l,int val) {
int r=n+1,mid,p=l;
while(l<r) if(query(p,mid=l+r>>1,0)<val) r=mid; else l=mid+1;
return l;
}
int getmx(int l,int val) {
int r=n+1,mid,p=l;
while(l<r) if(query(p,mid=l+r>>1,1)>val) r=mid; else l=mid+1;
return l;
}
ll ans[maxn];
int main() {
n=read();rep(i,1,n) A[i]=read();
init();int cnt=0;
rep(l,1,n) {
int mx=A[l],mn=A[l],r=l;
while(r<=n) {
int p=min(getmn(r+1,mn),getmx(r+1,mx));
cnt++;ans[p-l]=max(ans[p-l],(ll)mx*mn);
r=p;mn=min(mn,A[r]);mx=max(mx,A[r]);
}
}
dwn(i,n,1) ans[i]=max(ans[i],ans[i+1]);
rep(i,1,n) printf("%lld\n",ans[i]);
return 0;
}

E 刷题计划

一般来说,这类二维乘积最小的问题都可以通过类似二维乘积最小生成树的方法解决。

对于一个代码量之和=x,无聊值之和=y的方案,我们将(x,y)这个点放到平面直角坐标系上,那么整个问题的答案可以看成一个关于x的函数。

不难证明,最优方案只有可能是下凸壳上的点(用反比例函数)。

那么我们可以使用分治算法来解决这个问题,如果我们已经找到了两个决策点A、B,且A在B的左上方,我们每次只需找到一个在线段AB下方的凸点P,进一步分析问题可得,我们选与在AB垂线上投影尽量短的向量OP即可。如果找到了我们就可以分治子问题了。

那么这样的点怎么找呢?因为向量和的内积=向量内积的和,我们将每个物品的价值变成向量(bi,ci)在AB垂线上的射影长度,之后就是经典的背包问题,做一次简单的DP就可以得到方案了。

时间复杂度为期望O(sqrt(N)*N*M)

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=410;
const int maxm=810;
int n,m,M,A[maxn];
typedef long long ll;
struct Point {
ll x,y;
};
double w[maxn],f[maxn][maxm];
ll ans,B[maxn],C[maxn];
int use[maxn],g[maxn][maxm];
double cal(Point a,Point b) {
ll k=a.x*b.x+a.y*b.y;
return (double)k/sqrt(b.x*b.x+b.y*b.y);
}
void print(int i,int j) {
if(!i) return;
if(g[i][j]) use[i]=1,print(i-1,j-A[i]);
else use[i]=0,print(i-1,j);
}
void work(Point P1,Point P2) {
Point k=(Point){P1.y-P2.y,P2.x-P1.x};
f[0][0]=0;rep(i,1,M) f[0][i]=1e100;
rep(i,1,n) {
w[i]=cal((Point){B[i],C[i]},k);
rep(j,0,M) {
if(j<A[i]||f[i-1][j]<f[i-1][j-A[i]]+w[i]) f[i][j]=f[i-1][j],g[i][j]=0;
else f[i][j]=f[i-1][j-A[i]]+w[i],g[i][j]=1;
}
}
int x=m;
rep(i,m+1,M) if(f[n][i]<f[n][x]) x=i;
print(n,x);
ll s1=0,s2=0;
rep(i,1,n) if(use[i]) s1+=B[i],s2+=C[i];
ans=min(ans,s1*s2);
if(P1.x==s1&&P1.y==s2) return;
if(P2.x==s1&&P2.y==s2) return;
work(P1,(Point){s1,s2});work((Point){s1,s2},P2);
}
int main() {
n=read();m=read();
rep(i,1,n) M+=(A[i]=read()),B[i]=read(),C[i]=read();
ans=1ll<<60;work((Point){0,1e9},(Point){1e9,0});
printf("%lld\n",ans);
return 0;
}

F 货物运输

设传送站分别设在x和y,且x<y。

考虑二分答案ans,将所有R[i]-L[i]>ans的路线拿出来,那么|L[i]-x|+|R[i]-y|<=ans。

将所有的(L[i],R[i])作为平面的点,那么问题就转化成在平面中寻找一个点P,满足P到其他的点的曼哈顿距离均<=ans。

坐标变换一下(将(x,y)变换成(x-y,x+y))将曼哈顿距离转化成切比雪夫距离,然后直接维护矩形交就行了。

时间复杂度为O(NlogN)。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=500010;
const int inf=1e9;
int n,m,L[maxn],R[maxn];
int check(int d) {
int x1=-inf,y1=-inf,x2=inf,y2=inf;
rep(i,1,m) if(R[i]-L[i]>d) {
int X1=L[i]-R[i]-d,Y1=L[i]+R[i]-d,X2=L[i]-R[i]+d,Y2=L[i]+R[i]+d;
if(x2<X1||x1>X2) return 0;
else x1=max(x1,X1),x2=min(x2,X2);
if(y2<Y1||y1>Y2) return 0;
else y1=max(y1,Y1),y2=min(y2,Y2);
}
return 1;
}
int main() {
n=read();m=read();int l=0,r=n,mid;
rep(i,1,m) {
L[i]=read();R[i]=read();
if(L[i]>R[i]) swap(L[i],R[i]);
}
while(l<r) if(check(mid=l+r>>1)) r=mid; else l=mid+1;
printf("%d\n",l);
return 0;
}

G 带可选字符的多字符串匹配

比较坑的是模式串可能有空格。

打个暴力结果不小心A了(不知所措),求神犇题解。。。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int maxn=2100010;
char s[maxn],tmp[310];
int n;
ll A[610];
int id(char c) {
if(isdigit(c)) return c-'0';
if(c>='a'&&c<='z') return c-'a'+10;
if(c>='A'&&c<='Z') return c-'A'+36;
return 63;
}
int main() {
char c=getchar();int m=0;
while(c!='\n') s[++m]=c,c=getchar();
n=read();
rep(i,1,n) {
int k=read();
if(k) scanf("%s",tmp);
rep(j,0,k-1) A[i]|=1ll<<id(tmp[j]);
}
int is=0;
for(int i=1;s[i+n-1];i++) {
int ok=1;
rep(j,1,n) if(!(A[j]>>id(s[i+j-1])&1)) {ok=0;break;}
if(ok) printf("%d\n",i),is=1;
}
if(!is) puts("NULL");
return 0;
}

  

51nod百度之星2016练习赛的更多相关文章

  1. BestCoder 百度之星2016

    20160523 百度之星初赛第一场 1001 All X Problem Description F(x, m)F(x,m) 代表一个全是由数字xx组成的mm位数字.请计算,以下式子是否成立: F( ...

  2. 百度之星2016资格赛D,水题

    很简单的题,主要是要用字符串哈希,把字符串处理成整数.接下来可以继续用hash,也可以像我一样用个map就搞定了. /* * Author : ben */ #include <cstdio&g ...

  3. 2016百度之星 初赛2A ABEF

    只做了1001 1002 1005 1006.剩下2题可能以后补? http://acm.hdu.edu.cn/search.php?field=problem&key=2016%22%B0% ...

  4. 2016百度之星 资格赛ABCDE

    看题:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=690 交题:http://acm.hdu.edu.cn/search.php ...

  5. HDU 5690:2016"百度之星" - 初赛 All X

    原文链接:https://www.dreamwings.cn/hdu5690/2657.html All X Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  6. HDU 5688:2016"百度之星" - 资格赛 Problem D

    原文链接:https://www.dreamwings.cn/hdu5688/2650.html Problem D Time Limit: 2000/1000 MS (Java/Others)    ...

  7. HDU 5686:2016"百度之星" - 资格赛 Problem B

    原文链接:https://www.dreamwings.cn/hdu5686/2645.html Problem B Time Limit: 2000/1000 MS (Java/Others)    ...

  8. HDU 5685:2016"百度之星" - 资格赛 Problem A

    原文链接:https://www.dreamwings.cn/hdu5685/2637.html Problem A Time Limit: 2000/1000 MS (Java/Others)    ...

  9. 2016"百度之星" - 初赛(Astar Round2A)HDU 5695 拓扑排序+优先队列

    Gym Class Time Limit: 6000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

随机推荐

  1. java中常用的工具类(一)

    我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...

  2. poj 3349:Snowflake Snow Snowflakes(哈希查找,求和取余法+拉链法)

    Snowflake Snow Snowflakes Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 30529   Accep ...

  3. Spring XML配置文件示例(一)——<Servlet name>-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  4. 如何在ASP.NET 5中使用ADO.NET

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ASP.NET 5是一个全新的平台,在这个平台上也带来一些全新的函数库.不过这并非意味 ...

  5. mysql 方法row_number()方法

    1.  SELECT  t.*,        @curRow := @curRow + 1 AS row_numberFROM    structure tJOIN    (SELECT @curR ...

  6. LeetCode——Single Number(找出数组中只出现一次的数)

    问题: Given an array of integers, every element appears twice except for one. Find that single one. No ...

  7. CF735C 数论\平衡树叶子节点的最大深度\贪心\斐波那契\条件归一化

    http://codeforces.com/problemset/problem/735/C 题意..采用淘汰赛制..只要打输就退出比赛..而且只有两个选手打过的场数 相差不超过1才能比赛..最后问你 ...

  8. 【转】使用jquery animate创建平滑滚动效果

    这篇文章主要介绍了使用jquery animate创建平滑滚动效果,效果可以滚动到顶部.到底部或页面中指定地方,生要的是非常平滑,很舒服,需要的朋友可以参考下 滚动到顶部: $('.scroll_to ...

  9. LoadRunner参数化之数据取值和更新方式

    其实看LR已经很久了,每次看到参数化的取值更新时,都没有看透,了解个大概就为止了,也确实挺搞脑子的. 现在理解下来 分成2部分 取值方式  Select next row 如何从数据列表中取值 Seq ...

  10. POJ 2002 统计正方形 HASH

    题目链接:http://poj.org/problem?id=2002 题意:给定n个点,问有多少种方法可以组成正方形. 思路:我们可以根据两个点求出对应正方形[有2个一个在两点左边,一个在两点右边] ...