-TEST 18 for NOIP 。。。(0-300)

头更更大

这个10月完就要去搞NOIP了。。。

10月30天也就3次测试。。。为保佑进省一我还是每次测试玩都写个总结。。


不想说话。三道题第一眼下去都不可做。。。
第一题没有及时取模炸了。
第二题自己乱推规律炸了。
第三题。。。。。。

总之最后就爆0了。。。

这里写图片描述
看来是时候练一波暴力了。。。orz

下面详细解答:

T1(0/100):区间

problem

题意:给你一个区间,接着是q个询问< x,y >,求序列的所有区间中数字 x 的出现次数与数字 y 出现次数相同的区间的个数。
样例

  • 输入
    3 2
    1 2 1
    1 2
    4 5

  • 输出
    2
    6

solution

按理说这是T2级别的。

本来想的是打个8000x8000的数组暴力的。。。然而由于哈希没有及时取模被炸成RE。。。。。
哈希表记得一开始就取模。。。orz

正解。。详见题解吧。。。感觉再遇到了还是不可做。。

T2(80/100):做运动

problem

题意:对于一个1~n的排列,若知到每一位的逆序数,就能求得原排列。现在规定P[i]=a[1]~a[i]的逆序数和。给你这个序列的逆序数和,求这个排列。逆序数的定义是在序列的这一位数之前的所有大于这个数的数的个数。
样例

  • 输入
    3
  • 输出
    0 1 2

solution

首先可以根据逆序数为0的最后一位来确定序列最大数的位置。然后删除这个数的影响(这一位的逆序数赋为无穷大,位数在它之后的数的逆序数依次减1),再重新确定第二大的数的位置。
可以用线段树或者树状数组实现。

T3(30/100):边的处理

problem

题意
有一个n个点的无向图,给出m条边,每条边的信息如< x,y,c,r >。
给出q组询问形如< u,v,l,r >。
询问表示:一开始你在点u上,然后按顺序处理编号从 l 到 r 的边。
对于一条边< x,y,c,r >,你可以进行两种操作:
1.如果你当前在x点或者y点上,那么你可以走这条边并付出c的代价。
2.如果你不走这条边或者不可以走这条边(即你当前不在x或y上),那么你需要付出r的代价。
询问如果要从点u开始,按顺序处理完编号从l到r的边之后到达v点的最小代价,如果不能到达v,那么输出-1.
边和点的编号从1开始。
样例

  • 输入 
    5 5 3
    1 4 4 5
    4 1 6 1
    2 1 2 9
    2 5 1 0
    1 5 2 5
    2 2 2 4
    5 4 5 6
    1 5 2 5

  • 输出
    10
    -1
    9

solution

题解是分治?????

感想

今天是真正遇到了不可做题。。。也多少总结一下遇到不可做题的方法:
1.首先在心理上千万不能慌张,就像当时慌张导致所有的暴力都没有打对。要沉住气,你觉得难的题大佬一般也不会好到哪里去(当然凯爷啊,wjmzbmr这些大神不算)
2.必须每道题打上暴力,而且打完暴力后准备好对拍程序,再想正解。这次的一个重大误判就是第二题自己造了7个小数据都没有问题。所以暴力要大好(最好是分段针对特定范围的)
3.多想想基础的数据结构,最近的一连串考试中栈,队列,链表等数据结构,递归,搜索,回溯等基础算法出现频率很高,要引起重视。
4.要多想,要多想!

最后:多练模板!!!

代码:

T1:

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

char ch;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

const int nod=25000;
int n,m,l,r,x,y;
int t1,t2,tt,ans;
int f[8010][8010];
int a[8010],next[8010];
int hash[nod+3];
int first[nod+3];
int s,t[16010];

inline void insert(int x)
{
    int y=x%nod;
    while(hash[y]!=0&&hash[y]!=x)y=(y+1)%nod;
    hash[y]=x;
}

inline int loc(int x)
{
    int y=x%nod;
    while(hash[y]!=0 && hash[y]!=x)y=(y+1)%nod;
    return (hash[y]==x)?(y):(nod+1);
}

int main()
{
    memset(f,128,sizeof(f)); 
    n=read(),m=read();

    for(int i=1;i<=n;++i)a[i]=read(),++a[i],insert(a[i]);

    for(int i=n;i>=1;--i)x=loc(a[i]),next[i]=first[x],first[x]=i;

    first[nod+1]=n+1;
    for(int i=1;i<=m;++i)
    {
        x=read(),y=read();++x,++y;  
        if(f[first[loc(x)]][first[loc(y)]]<0)
        {
            memset(t,0,sizeof(t));
            s=l=r=n,ans=0,tt=0;
            t1=first[loc(x)],t2=first[loc(y)];

            while(t1>0||t2>0)
            {
                (t2==0||(t1<t2 && t1!=0))?
                (t[s]+=t1-tt,++s,r=max(r,s),tt=t1,t1=next[t1]):
                (t[s]+=t2-tt,--s,l=min(l,s),tt=t2,t2=next[t2]);
            }

            t[s]+=n-tt+1;

            for(register int j=l;j<=r;++j)
                ans+=(t[j]-1)*t[j]/2;

            f[first[loc(x)]][first[loc(y)]]=ans;
        }
        else ans=f[first[loc(x)]][first[loc(y)]];

        cout<<ans<<endl;
    }
    return 0;

}

T2

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

int n,u;
int a[100010];
int c[100010];
int p[100010];
vector<int>v;

int main() 
{
    n=read();
    for(int i=1;i<=n;++i)
    {
        c[i]=read();
        v.push_back(i);
    }
    vector<int>::iterator it;
    for(int i=n;i>=1;--i) 
    {
        c[i]-=c[i-1];
        it = v.begin()+i-1-c[i];
        a[i] = *it;
        v.erase(it);
    }
    for(int i=1;i<=n;++i) cout<<a[i]<<" ";
    return 0;
}

T3

std.cpp(代码来自zwk)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')f=-1,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=35,M=20005;
const int INF=0x3f3f3f3f;
struct node
{
    int s,t,l,r,id;
}q[200005],d[200005];
struct edge
{
    int x,y,w1,w0;
}bian[M];
int n,m,Q;
int ans[200005],f[M][N][N],g[M][N][N];

void solve(int l,int r,int L,int R)
{
    if(l>r||L>R)return;
    int mid=l+r>>1;
    int i,x,y;
    for(i=l-1;i<=r+1;i++)
        for(x=1;x<=n;x++)
            for(y=1;y<=n;y++)
                f[i][x][y]=g[i][x][y]=INF;
    for(x=1;x<=n;x++)f[mid+1][x][x]=0;
    for(i=mid;i>=l;i--)
        for(x=1;x<=n;x++)
        {
            f[i][x][x]=f[i+1][x][x]+bian[i].w0;
            for(y=1;y<=n;y++)
            {
                if(x==bian[i].x)
                    f[i][x][y]=min(f[i][x][y],f[i+1][bian[i].y][y]+bian[i].w1);
                if(x==bian[i].y)
                    f[i][x][y]=min(f[i][x][y],f[i+1][bian[i].x][y]+bian[i].w1);
                f[i][x][y]=min(f[i][x][y],f[i+1][x][y]+bian[i].w0);
            }
        }
    for(x=1;x<=n;x++)g[mid][x][x]=0;
    for(i=mid+1;i<=r;i++)
        for(x=1;x<=n;x++)
        {
            g[i][x][x]=g[i-1][x][x]+bian[i].w0;
            for(y=1;y<=n;y++)
            {
                if(y==bian[i].x)
                    g[i][x][y]=min(g[i][x][y],g[i-1][x][bian[i].y]+bian[i].w1);
                if(y==bian[i].y)
                    g[i][x][y]=min(g[i][x][y],g[i-1][x][bian[i].x]+bian[i].w1);
                g[i][x][y]=min(g[i][x][y],g[i-1][x][y]+bian[i].w0);
            }
        }
    int R1=L-1,L1=R+1;
    for(i=L;i<=R;i++)
    {
        if(q[i].l<=mid&&mid<=q[i].r)
            for(x=1;x<=n;x++)
                ans[q[i].id]=min(ans[q[i].id],f[q[i].l][q[i].s][x]+g[q[i].r][x][q[i].t]);
        else if(q[i].r<mid)d[++R1]=q[i];
        else if(q[i].l>mid)d[--L1]=q[i];
    }
    for(int i=L;i<=R;i++)
        q[i]=d[i];
    solve(l,mid-1,L,R1);
    solve(mid+1,r,L1,R);
}

int main()
{
    //freopen("lx.in","r",stdin);
    n=getint(),m=getint(),Q=getint();
    for(int i=1;i<=m;i++)
    {
        bian[i].x=getint(),bian[i].y=getint();
        bian[i].w1=getint(),bian[i].w0=getint();
    }
    for(int i=1;i<=Q;i++)
    {
        q[i].s=getint(),q[i].t=getint();
        q[i].l=getint(),q[i].r=getint();
        q[i].id=i,ans[i]=INF;
    }
    solve(1,m,1,Q);
    for(int i=1;i<=Q;i++)
        if(ans[i]==INF)puts("-1");
        else cout<<ans[i]<<'\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值