20171002模拟赛

一看今天的题

T1 bzoj1528 T2 poj2948 T3poj2828

做你********************************************************

本来想打开电脑上的希尔薇

然后看T3 这他喵的不是线段树吗

然后毅然拿出了自己祖传的ZKW线段树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,k;
int M;
int tr[200010*4],p[200010],v[200010],ans[200010*4];
inline void change(int k){for(int i=k+M;i;i>>=1)tr[i]++;}
inline void insert(int x,int y)
{
     int i=1;
     while(i<M)
     {
        tr[i]--;i<<=1;
        if(tr[i]<x)x-=tr[i],i|=1;
     }     
     tr[i]--,ans[i-M]=y;
}
int main()
{
    freopen("queue.in","r",stdin);
    freopen("queue.out","w",stdout);
    while(~scanf("%d",&n))
    {
        memset(p,0,sizeof(p));
        memset(v,0,sizeof(v));
        for(M=1;M<n;M<<=1);
        for(int i=0;i<n;i++)change(i);
        for(int i=0;i<n;i++)scanf("%d%d",p+i,v+i);
        for(int i=n-1;i>=0;i--)insert(p[i]+1,v[i]);
        for(int i=0;i<n;i++)printf("%d ",ans[i]);
        printf("\n");
    }
    return 0;
}
View Code

然后发现不知比高一轩同学的普通线段树low到哪里去了

所以从网上找了个普通线段树的板子发一下

from

http://www.cnblogs.com/ACMan/archive/2012/07/11/2586793.html

这题想到了就水了,数据逆着插入,最先插入的一个数据的位置明显是题目给定的位置,可以确定,然后插入的几个数根据的位置前面插入的数据来决定,

用sum[]数组表示改线段空位置的个数,满足 pos<=sum[rt<<1](即左儿子的空位多于插入数的位置序号)就访问左儿子,否则访问右儿子

(访问右节点的时候注意pos要修改,改为pos-sum[rt],即整个线段的第pos个空位,在下一个右儿子那的第pos-sum[rt]个空位)。

#include<stdio.h>
#include<string.h>

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mid int m = (l + r)>>1
#define maxn 200000

int sum[maxn<<2],pos[maxn],val[maxn],ans[maxn<<2];//ans储存插入的值;

void push_up(int rt)
{
    sum [rt] = sum[rt<<1]+sum[rt<<1|1];
}
void build(int l, int r, int rt)
{
    sum[rt]=r-l+1;
    if(l == r)return;
    mid;
    build(lson);
    build(rson);
}
void update(int pos, int val, int l, int r, int rt)
{
    if(l == r){ans[rt]=val;sum[rt]--;return;}
    mid;
    if(pos <= sum[rt<<1])update(pos, val, lson); //根据左右儿子空位的多少和插入数据的位置比较来确定插入哪个儿子
    else update(pos -sum[rt<<1], val, rson);
    push_up(rt);
}
void print(int l, int r, int rt)
{
    if(l == r){printf("%d ",ans[rt]);return;}
    mid;
    print(lson);
    print(rson);
}
int main()
{
    int n,i;
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;i++)
            scanf("%d%d",&pos[i],&val[i]);
        build(1, n ,1);
        for(i=n-1;i>=0;i--)
            update(pos[i]+1, val[i], 1, n, 1);
        print(1, n, 1);
        printf("\n");
    }
    return 0;
}
View Code

谢谢大神orz 侵删

但是因为高一轩同学非常的仁慈(时限5s) 所以这题我100分

然后开始搞T1

思路很简单啊 为了不为难男主滴妈妈 我们每次拿进来一个东西就把“最不可能用到”的东西拿出去 而“最不可能用到”可以表示为“下次出现时最远”

于是优先队列

小细节:如果新来的点的val等于原来点的val

要将这个点进队 更新pos

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct p
{
    int pos,val;
    bool operator < (const p &a)const
    {
        return pos < a.pos;
    }
}c[500010];
priority_queue<p> q;
bool inq[500010];
int hash[1000010];
int n,k,p,ans;
int main()
{
    freopen("book.in","r",stdin);
    freopen("book.out","w",stdout);
    n=read();k=read();p=read();
    for(int i=1;i<=p;i++)
    {
        c[i].val=read();
        hash[c[i].val]=i;
    }
    for(int i=p;i>=1;i--)
    {
        if(hash[c[i].val]!=i)c[i].pos=hash[c[i].val];
        else c[i].pos=2147483233;
        hash[c[i].val]=i;
    }
    for(int i=1;i<=k;i++)
    {
        if(!inq[c[i].val])
        {
            q.push(c[i]);
            inq[c[i].val]=1;
            ans++;
            //cout<<i<<" "<<c[i].val<<" "<<endl;
            //system("pause");
        }
        else 
        {
            q.push(c[i]);
            k++;
        }
    }
    for(int i=k;i<=p;i++)
    {
        if(inq[c[i].val]){q.push(c[i]);continue;}
        if(!inq[c[i].val])
        {
            ans++;
            inq[c[i].val]=1;
            inq[q.top().val]=0;
            q.pop();
            q.push(c[i]);
            //cout<<i<<" "<<c[i].val<<" "<<endl;
            //system("pause");
        }
    }
    printf("%d",ans);
}
View Code

一点小细节搞了几百年

最后打开了Force — AlanWalker

准备打T2的Force

然后发现!T2就是Force!

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int dp[505][505];
int x[505][505],y[505][505];

int n,m;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int main()
{
    freopen("ore.in","r",stdin);
    freopen("ore.out","w",stdout);
    while(scanf("%d%d",&n,&m))
    {
        if(!n&&!m) return 0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            x[i][j]=read();   
            x[i][j]+=x[i][j-1];
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            y[i][j]=read();
            y[i][j]+=y[i-1][j];
        }

        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(i==1)
            {
                if(j==1) dp[i][j]=max(y[i][j],x[i][j]);
                else dp[i][j]=max(dp[i][j-1]+y[i][j],x[i][j]);
            }
            else 
            {
                if(j==1) dp[i][j]=max(y[i][j],dp[i-1][j]+x[i][j]);
                else dp[i][j]=max(dp[i][j-1]+y[i][j],dp[i-1][j]+x[i][j]);
            }
        }
        printf("%d\n",dp[n][m]);
    }
}
View Code

我从最难的做起 一路做到了最简单的

呵呵

AK

 

posted @ 2017-10-02 13:31  探险家Mr.H  阅读(206)  评论(0编辑  收藏  举报