2018.10.05 练习赛

[T1 序列计数]

题解:

\(DP\)可做,\(F[i][j]\),表示第\(i\)个数组成的好序列左边差\(j\)个数时的方案数;

\(code\):

#include<stdio.h>
#include<algorithm>
#include<ctype.h>
#define mod 998244353
using namespace std;

inline int add(int a,int b){return a+b<mod?a+b:a+b-mod;}

int n,a[5005],f[5005][5005];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    if(a[1]>0&&a[1]<=n-1) f[1][a[1]]=1;
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            f[i][j]=f[i-1][j];
            if(j) f[i][j-1]=add(f[i][j-1],f[i-1][j]); 
        }
        if(a[i]>0&&a[i]<=n-1) f[i][a[i]]=add(f[i][a[i]],f[i-1][0]+1);   
    }
    printf("%d",f[n][0]);
}
 

[T2 僵尸大战植物引发的惨♂案 ]

题解:

预处理出对于一个点\(S\),起点到他的距离,他一路坐到站底时的最优时间(坐到站底\(T\)的时间\(+\)坐到终点的时间),把这个当成边丢进\(vector\),二分一个答案验证;

\(code:\)

#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll N=25001,inf=1e18;
struct www{
    ll to,len;
    www(ll to=0,ll len=0):
        to(to),len(len){}
    bool operator<(const www x)const{
        return len>x.len;
    }
};
priority_queue<www>q;
vector<www>g[N],qwq[N];
ll n,m,s,t,lim,w[N],sum[N],sub[N],dis[N];
void dijkstra(ll s,bool f){
    for(ll i=0;i<n;i++)dis[i]=inf;
    q.push(www(s,0));dis[s]=0;
    while(!q.empty()){
        ll x=q.top().to,_dis=q.top().len;
        q.pop();if(dis[x]!=_dis)continue;
        for(ll i=g[x].size()-1;i>=0;i--){
            ll y=g[x][i].to,len=g[x][i].len+_dis;
            bool ok=f|(len+qwq[x][i].len<=lim);
            if(dis[y]>len&&ok)dis[y]=len,q.push(www(y,len)); 
        }
    }
}
int main(){
    scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
    for(ll i=1;i<=m;i++){
        scanf("%lld",&sub[0]);
        for(ll j=1;j<=sub[0];j++)scanf("%lld",&sub[j]);
        for(ll j=1;j<sub[0];j++){
            scanf("%lld",&w[j]);
            sum[j]=sum[j-1]+w[j]; 
        }
        for(ll j=1;j<sub[0];j++){
            g[sub[j]].push_back(www(sub[j+1],w[j]));
            g[sub[j+1]].push_back(www(sub[j],w[j]));
            qwq[sub[j]].push_back(www(sub[sub[0]],sum[sub[0]-1]-sum[j]));
            qwq[sub[j+1]].push_back(www(sub[1],sum[j-1]));
        }
    }
    dijkstra(t,1);
    for(ll i=0;i<n;i++)
    for(ll j=qwq[i].size()-1;j>=0;j--)
    qwq[i][j].len+=dis[qwq[i][j].to];
    ll l=0,r=inf;
    while(l<=r){
        lim=l+r>>1;
        dijkstra(s,0);
        if(dis[t]==inf)l=lim+1;
        else r=lim-1;
    }
    printf("%lld",l);
}

[T3 深夜放毒]

题解:

说实话想到很简单,写起来确实恶心,典型的树套树,横向维护一颗线段树,纵向维护一颗线段树,不想写=_=,于是放上出题人自己的代码

\(code:\)

#include <stdio.h>
#include <iostream>
#include <algorithm>
#define ll long long 
using namespace std;
int k,lim;
const int QAQ=20000000;
int ls[QAQ],rs[QAQ];
ll sum[QAQ],lazy[QAQ];
int tot=1;
void mdf(int now,int l,int r,int x,int y,ll v)
{
    if(x<=l&&y>=r)
    {
        sum[now]+=(r-l+1)*v;
        lazy[now]+=v;
        return;
    }
    int mid=l+r >>1;
    if(lazy[now])
    {
        ll v=lazy[now];
        lazy[now]=0;
        if(!ls[now])ls[now]=++tot;
        if(!rs[now])rs[now]=++tot;
        sum[ls[now]]+=(mid-l+1)*v;
        sum[rs[now]]+=(r-mid)*v;
        lazy[ls[now]]+=v;
        lazy[rs[now]]+=v;
    }
    if(x<=mid)
    {
        if(!ls[now])ls[now]=++tot;
        mdf(ls[now],l,mid,x,y,v);
    }
    if(y>mid)
    {
        if(!rs[now])rs[now]=++tot;
        mdf(rs[now],mid+1,r,x,y,v);
    }
    sum[now]=sum[ls[now]]+sum[rs[now]];
}
ll get(int now,int l,int r,int x,int y)
{
    if(!now)return 0;
    if(x<=l&&y>=r)return sum[now];
    int mid=l+r >>1;
    ll tmp=0;
    if(lazy[now])
    {
        ll v=lazy[now];
        lazy[now]=0;
        if(!ls[now])ls[now]=++tot;
        if(!rs[now])rs[now]=++tot;
        sum[ls[now]]+=(mid-l+1)*v;
        sum[rs[now]]+=(r-mid)*v;
        lazy[ls[now]]+=v;
        lazy[rs[now]]+=v;
    }
    if(x<=mid)tmp+=get(ls[now],l,mid,x,y);
    if(y>mid)tmp+=get(rs[now],mid+1,r,x,y);
    return tmp;
}
int lb(int x)
{return x&(-x);}
void MODIFY(int xxx,int x,int y,ll v)
{while(xxx<=k)mdf(xxx,0,lim-1,x,y,v),xxx+=lb(xxx);}
ll QUERY(int xxxx,int x)
{ll t=0;while(xxxx)t+=get(xxxx,0,lim-1,x,x),xxxx-=lb(xxxx);return t;}
char buf[1<<20],*p1,*p2;
#define GC (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?0:*p1++)
inline int R()
{
    int p=0;
    char o=GC;
    while(o<48||o>57)o=GC;
    while(o>=48&&o<=57)
    {
        p=(p<<1)+(p<<3)+o-48;
        o=GC;
    }
    return p;
}
void FangDu()
{
    int x=R(),h=R();
    ll v=R();
    mdf(k+1,0,lim-1,x/k-h,x/k,v);
    mdf(k+1,0,lim-1,(x+1)/k,(x+1)/k+h,-v);
    MODIFY(x%k+1,x/k-h,x/k,v);
    MODIFY((x+1)%k+1,(x+1)/k,(x+1)/k+h,-v);
}
void XunWen()
{
    int x=R();
    int alk=(x+1)/k-1;
    ll ans=0;
    if(alk>=0)
        ans+=get(k+1,0,lim-1,0,alk);
    if((x+1)%k!=0)
        ans+=QUERY(x%k+1,x/k);
    printf("%lld\n",ans);
}
//Please Do Not Diss Me !!!!
int main()
{
    k=R(),lim=R();
    int i,m=R();
    tot=k+1;
    while(m--)
    {
        i=R();
        if(i==1)FangDu();
        else XunWen();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/KatouKatou/p/9745840.html