-TEST 20 for NOIP 。。。(80-300)-----(( ! ))

头更更更大

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

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


boomshakalaka,不说了
严重怀疑我会一直炸到NOIP复赛。。。

第一题秒岀正解,看到数据范围想开快速乘然后自己过数据的时候卡到爆炸,然后看最后要对int的数取模就没有用了。。。。。。然后最后两个点卡爆。=

第二题难得清醒一回看出来了是几个基环外向树(当时不知道这个名字)然后觉得很简单就去搞了。
然后这个很简单的代价就是代码量大到爆炸然后我就炸了,没写暴力。
侧面也反映出自己代码还不够简洁与模块化。

第三题更是作死又因为忘了数据范围是long long连20分的暴力都没拿到。正解是个线段树。。。怕是考试时很多人把T3打了暴力就不管去怼T2了。

总之一句话,自己作死不把暴力打好。

昨晚23:30之前睡今早考试状态超好。。然而因为已经连续一个月没好好睡了外加上一周莫名心态爆炸还是显得有点迟钝。

怕是药丸。

这里写图片描述

下面面详细解答:

T1(80/100):数列求和

problem

题意:给你一个序列,问你这个序列所有子段的元素积之和。最后结果对p取模。
样例

  • 输入
    3 997
    2 3 5
  • 输出
    61

solution

考试时第一个反应是前缀和。
再一看题不对,那大不了改成前缀积。
先求出以a1为序列首位元素的子段的积之和然后O(n)向后扫遇见一个除一个减一就行。
但是同余提前取模要爆炸,那就从后往前取(事实上往哪个方向取都一样),搞定。

然后最后两个点没有开 long long 爆炸。

T2(0/100):路径统计

problem

题意:给你一个n个点n条边的图,规定如果i -> j 不可达那么其路径权值为 -1(但是 i <- j 可能可达)。求这个图任意两点最短路径之和。答案对1000000007取模。
样例

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

  • 输出
    12

  • 输入
    2
    1 1
    2 2

  • 输出
    1000000005

solution

30%的数据就是Floyed都能跑过。。。
100%的数据比较繁琐,但是如果对于统计图中两两点最短路之和比较熟悉的话还是挺好做的。
然而我不熟悉,代码能力一般般甚至比最开始停课那一会还差一些,加上没有模块化,最后把自己绕死了。

可见暴力的重要性。

T3(0/100):小店购物

problem

题意
一道看起来像背包可以用贪心暴力然而正解是线段树的问题。
有n个商品,每个商品有价值w与价格p两种属性,接下来有m个操作,可能会对某一件商品的w,p进行修改,也可能是询问用K元能买下的商品价值总和。
购买的原则是:在可购买范围内,优先购买价值大的商品。如果有价值相同的,优先买价格低的。
每种商品数量无限。
样例

  • 输入 
    3 3
    1 1
    2 2
    3 3
    2 10
    1 1 6 6
    2 10

  • 输出
    10
    9

solution

一开始不知道我哪根筋抽了想到了背包+线段树。。。
后来发现算了算了打个暴力就溜了回去检查T2。(最后公布的正解并不很会。。)
然后又被 long long 阴了一波。

可见打个正确的暴力的重要性与必要性。

感想

多练模板!!!多打暴力!!!

代码:

T1:

my/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;
typedef long long ll;

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;
}

inline ll red()
{
    ll 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;
}

ll ksc(ll x,ll y,ll z)//快速乘 
{
    ll ans=0;
    while(y>0)
    {
        if(y&1)ans=(ans+x)%z;
        y=y>>1;
        x=(x+x)%z;
    }
    return ans;
}

int n;
ll p,s[100050];
int main()
{
    std::ios::sync_with_stdio(false);std::cout.tie(0);
    n=read();p=red();
    for(int i=1;i<=n;i++)s[i]=red();
    ll jud=0,ans=0;
    if(p<=1e10)
    for(int i=n;i>=1;i--)
    {
        jud = ((jud+1)*s[i])%p;
        ans = (ans+jud)%p;
    }
    else
    for(int i=n;i>=1;i--)
    {
        jud = ksc((jud+1),s[i],p);
        ans = (ans+jud)%p;
    }   
    cout << ans << endl;
    return 0;
}

T2

my.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;
}

const int kkk=500500;
const int mod=1000000007;

int n;
int first[kkk],cnt=0;
struct node{int u,v,val,next;}side[2*kkk];
void add(int u,int v,int val)
{
    side[++cnt].u=u;
    side[cnt].v=v;
    side[cnt].val=val;
    side[cnt].next=first[u];
    first[u]=cnt;
}

int tot,top;
int stk[kkk],belong[kkk],dfn[kkk],low[kkk],visit[kkk],num[kkk];
int tarjan(int u)
{
    dfn[u]=low[u]=++cnt;
    stk[++top]=u;
    visit[u]=true;
    for(int i=first[u];i;i=side[i].next)
    {
        int v=side[i].v;
        if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}
        else if(visit[v]){low[u]=min(low[u],dfn[v]);}
    }
    if(dfn[u]==low[u])
    {
        tot++;int v=-1;
        while(u!=v)
        {
            v=stk[top--];
            belong[v]=tot;
            num[tot]++;
            visit[v]=false;
        }
    }
}
int hh[kkk],gg[kkk];
int partv[kkk],exist[kkk],value[kkk];
int kooky,CNT,flag;
void dfs(int U,int pre,int check)
{
    if(U==pre){kooky=0;CNT=0;flag=0;exist[pre]=true;}
    CNT++;

    int i=first[U];
    int V=side[i].v;

    kooky+=side[i].val;
    partv[pre]+=kooky;

    while(V!=pre&&!exist[V]&&!flag)
    {
        visit[U]=true;
        dfs(V,pre,check);
        visit[U]=false;
    }
    if(!flag)
    {
        flag=1;     
        if(V!=pre)
        {
            partv[pre]=1ll*(partv[pre]+(partv[V]-partv[pre]-CNT*(value[check]-kooky)))%mod; 
            partv[pre]=1ll*(partv[pre]+(num[check]-CNT)*kooky)%mod;
        }
        else {partv[pre]-=kooky;}
    }
}

int krank[kkk];
void cfs(int ui)
{
    exist[ui]=true;
    int ii=first[ui];
    int vi=side[ii].v;
    if(ui==vi){partv[ui]=1-n;}

    while(!exist[vi])cfs(vi);
    if(!gg[belong[vi]])
    {
        partv[ui]=1ll*(partv[vi]+krank[vi]*side[ii].val+1)%mod;
        krank[ui]=1ll*(krank[vi]+1)%mod;
        return;
    }
    else
    {
        partv[ui]=1ll*(side[ii].val*num[belong[vi]]+partv[vi]-(n-num[belong[vi]]-1))%mod;
        krank[ui]=1ll*(num[belong[vi]]+1)%mod;
    }
}

int u,v,val;
int ans;

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);std::cout.tie(0);

    n=read();
    for(register int i=1;i<=n;i++)
    {
        v=read();val=read();
        add(i,v,val);
    }cnt=0;

    for(register int i=1;i<=n;++i)if(!dfn[i])tarjan(i);cnt=0;

    for(register int i=1;i<=n;++i)
    {
        u=side[i].u;
        v=side[i].v;
        if(u!=v)
        {
            if(belong[u]==belong[v])
            {
                if(!gg[belong[v]])
                {
                    hh[++cnt]=belong[u];
                    gg[belong[u]]=cnt;                  
                }
                value[belong[u]]+=side[first[u]].val;   
            }       
        }
    }

    for(register int i=1;i<=n;++i)
        if(gg[belong[i]])
            dfs(i,i,belong[i]); 

    for(register int i=1;i<=n;++i)
        if(!exist[i])
            cfs(i);

    for(register int i=1;i<=n;++i)
    {       
        if(gg[belong[i]]) partv[i]-=(n-num[belong[i]]);
        ans = 1ll*(ans+partv[i]+mod)%mod;
    }

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

std.cpp

话说这道题如果不开栈正解是会RE的。来自WTY的代码。

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

const int ooo=500050;
const int mod=1e9+7;

int n,to[ooo];
int low[ooo],dfn[ooo],stk[ooo],top,cnt,tot,belong[ooo];
bool jud2[ooo],jud1[ooo],vis[ooo],hu[ooo];
long long ans,sum,size[ooo],dis[ooo],val[ooo],num[ooo],f[ooo],w[ooo];
long long VAL,NUM;

inline long long read()
{
    long long 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;
}

void tarjan(long long u){
    dfn[u]=low[u]=++cnt;
    stk[++top]=u;
    vis[u]=true;
    if(!dfn[to[u]]) {tarjan(to[u]);low[u]=min(low[u],low[to[u]]);}
    else if(vis[to[u]]) low[u]=min(low[u],dfn[to[u]]);
    if(dfn[u]==low[u])
    {
        tot++;int v=-1;
        while(u!=v)
        {
            v=stk[top--];
            size[tot]+=1;
            val[tot]+=w[v];
            belong[v]=tot;
            vis[v]=false;
        }
    }
}
void dfs_else(int x){
    jud2[x]=true;
    if(to[x]!=x)
    {
        if(!jud2[to[x]]) dfs_else(to[x]);
        f[x]=1ll*(f[to[x]]+w[x]*num[to[x]])%mod;
        num[x]=1ll*(num[to[x]]+1)%mod;
        return;
    }
}
void dfs_self(int x)
{
    vis[x]=true;
    if(to[x]!=x&&!vis[to[x]])
    {
        dis[to[x]]=1ll*(dis[x]+w[x])%mod;
        sum=1ll*(sum+dis[to[x]])%mod;
        dfs_self(to[x]);
    }
}
void dfs_tree(int x)
{
    jud2[x]=true;
    if(!jud2[to[x]]&&to[x]!=x)
    {
        f[to[x]]=1ll*(f[x]+VAL-w[x]*NUM)%mod;
        dfs_tree(to[x]);
    }
}
int main()
{
    int _q = 50 << 20;
    char *_p=(char*)malloc(_q)+_q;
    __asm__("movl %0, %%esp\n"::"r"(_p));
    //手工开栈

    n=read();
    for(int i=1;i<=n;++i)
    {
        to[i]=read();w[i]=read();
        if(to[i]!=i) jud1[to[i]]=1;
        else jud2[i]=true,num[i]=1;
    }
    tot=0;
    for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
    for(int i=1;i<=n;++i)
        if(size[belong[i]]!=1)
        {
            hu[i]=true;
            num[i]=1ll*size[belong[i]]%mod;
        }
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;++i)
        if(hu[i]&&!jud2[i])
        {
            dis[i]=0;sum=0;
            dfs_self(i);
            f[i]=sum;VAL=val[belong[i]];NUM=size[belong[i]];
            dfs_tree(i);
        }
    for(int i=1;i<=n;++i)
        if(!jud1[i]&&!jud2[i])
        {
            dis[i]=0;sum=0;
            dfs_else(i);
        }
    for(int i=1;i<=n;++i)
    {
        ans=1ll*(ans+f[i]-(n-num[i]))%mod;
    }
    cout<<(ans+mod)%mod<<endl;
}

T3

详细解答参考dalao -> scar_lyw
题解来自JLY。

std.cpp

#include<bits/stdc++.h>
using namespace std;

const int N=200005;

struct option
{
    int typ,x,w,p;
}opt[N];

int n,m;
int len,w[N],prc[N],seq[N],v[N],pos[N];
int mx[N<<2];

inline int read()
{
    int i=0,f=1;
    char ch;

    for(ch=getchar();!isdigit(ch);ch=getchar())

    if(ch=='-') f=-1;

    for(;isdigit(ch);ch=getchar())
        i=(i<<3)+(i<<1)+(ch^48);

    return i*f;
}

inline bool cmp(int a,int b)
{
    return v[a]<v[b];
}

inline void update(int k,int l,int r,int p,int v)
{
    if(l==r) {mx[k]=v;return;}

    int mid=(l+r)>>1;

    if(mid>=p) update(k<<1,l,mid,p,v);
    else       update(k<<1|1,mid+1,r,p,v);

    mx[k]=max(mx[k<<1],mx[k<<1|1]);
}

inline void modify(int x,int v,int p)
{
    update(1,1,len,prc[x],0);
    update(1,1,len,p,v);

    prc[x]=p;
}

inline int query(int k,int l,int r,int p)
{
    if(l>p)  return 0;
    if(l==r) return mx[k];

    int mid=(l+r)>>1;

    if(p<mid) return query(k<<1,l,mid,p);
    else      return max(mx[k<<1],query(k<<1|1,mid+1,r,p));
}

inline int qprc(int k,int l,int r,int p,int now)
{
    if(l==r) return v[l];

    int mid=(l+r)>>1;

    if(mid>p || mx[k<<1]==now) return qprc(k<<1,l,mid,p,now);
    else                       return qprc(k<<1|1,mid+1,r,p,now);
}

inline int find(int k)
{
    int l=0,r=len+1,mid;

    while(l<r-1)
    {
        mid=(l+r)>>1;

        if(v[mid]<=k) l=mid;
        else          r=mid;
    }

    return l;
}

int main()
{
    n=read(),m=read();

    for(int i=1;i<=n;++i)
    {
        w[i]=read();
        prc[i]=read();
        v[++len]=prc[i];
    }

    for(int i=1;i<=m;++i)
    {
        opt[i].typ=read();
        if(opt[i].typ==2) opt[i].x=read();
        else
        {
            opt[i]=(option){1,read(),read(),read()};
            v[++len]=opt[i].p;
        }
    }

    for(int i=1;i<=len;++i) 
        seq[i]=i;

    sort(seq+1,seq+1+len,cmp);
    sort(v+1,v+1+len);

    for(int i=1;i<=len;++i) 
        pos[seq[i]]=i;

    for(int i=1;i<=n;++i) 
        update(1,1,len,pos[i],w[i]),prc[i]=pos[i];

    int np=n;

    for(int i=1;i<=m;++i)
    {
        if(opt[i].typ==1) ++np,modify(opt[i].x,opt[i].w,pos[np]);
        else
        {
            int res=opt[i].x;long long ans=0;

            while(res)
            {
                int npos=find(res);
                int rtn=query(1,1,len,npos);

                if(!rtn) break;

                int price=qprc(1,1,len,npos,rtn);

                ans+=1ll*rtn*(res/price),res%=price;
            }

            cout<<ans<<endl;
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值