ACM-ICPC 2018 徐州赛区网络预赛

34 篇文章 3 订阅
16 篇文章 0 订阅

A、Hard to prepare

推公式+矩阵快速幂

但是推公式失败了,,推了很久,但是还是感觉能做。。。

赛后看他人题解,,推错了,m=2^k,假设从第1个排到第n-1个,第n个位置有(m-2)情况数有m*((m-1)^(n-2))*(m-2),其中当第1个位置和第n-1个位置数不同时,第n个确实时(m-2),但是若这两个位置相同,第n个位置是有(m-1)种,所以当两个相同时,少乘了1,加上那一次,就是想到于把n-1个点排,其中第n-1个点于第n个点的数相同,就是n-2个点的排列数。。

d[n]=m*((m-1)^(n-2))*(m-2)+d[n-2];因为n的数据不大,直接dfs就可以。。。没推出来实在可惜。。代码就不粘了,,代码就简单了。。

F、Features Track

水题,简单map应用

代码:

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

int n,k,x,y;

struct Node
{
    int x,y;
    bool operator<(const Node& aa) const
    {
        if(x==aa.x) return y<aa.y;
        return x<aa.x;
    }
    bool operator==(const Node& aa) const
    {
        if(x==aa.x&&y==aa.y)
            return true;
        return false;
    }
}node;

map<Node,int>mp[100010];

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int i,j,Max=-1;
        int cnt=0;
        //mp[0].clear();
        for(i=1;i<=n;i++)
        {
            mp[i].clear();
            //memset(mp[i],0,sizeof(mp[i]));
            scanf("%d",&k);
            for(j=1;j<=k;j++)
            {
                scanf("%d%d",&node.x,&node.y);
                mp[i][node] = mp[i-1][node]+1;
                //cout<<mp[i-1][node]<<"  "<<mp[i][node]<<endl;
                if(Max<mp[i][node])
                    Max=mp[i][node];
            }
        }
        printf("%d\n",Max);
    }
    return 0;
}

G、Trace

类似扫描线的树状数组、。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int hx[10000010],hy[10000010];
int xx[10000010],yy[10000010];
int n,m;
int lowbit(int x)
{
    return x&(-x);
}
void addx(int pos,ll x)
{
    while(pos<=n)
    {
        hx[pos]+=x;
        pos+=lowbit(pos);
    }
}
ll queryx(int pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=hx[pos];
        pos-=lowbit(pos);
    }
    return res;
}
void addy(int pos,ll x)
{
    while(pos<=n)
    {
        hy[pos]+=x;
        pos+=lowbit(pos);
    }
}
ll queryy(int pos)
{
    ll res=0;
    while(pos>0)
    {
        res+=hy[pos];
        pos-=lowbit(pos);
    }
    return res;
}
int main()
{
    int i;
    n=10000000;
    scanf("%d",&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&xx[i],&yy[i]);
    }
    int x,y;
    ll dx,dy,res=0;
    for(i=m;i>=1;i--)
    {
        x=xx[i];
        y=yy[i];
        x++;
        y++;
        dx=y-queryx(x)-1;
        dy=x-queryy(y)-1;
        res+=(dx+dy);
        addx(x-dy,dx);
        addx(x+1,-dx);
        addy(y-dx,dy);
        addy(y+1,-dy);
    }
    printf("%lld\n",res);
    return 0;
 }

H、Ryuji doesn't want to study

树状数组,转化一下公式,做两个树状数组

i∈[l,r],j∈[1,r],k∈[1,l],p∈[l+1,r];
∑(a[i]*(L-i+1))=L*∑a[i]-(∑a[i]*(L-i));
∑a[i]*(L-i)=∑(a[j]*j)-∑(a[l]*l)-((∑a[p])*l);

代码:

#include<bits/stdc++.h>
using namespace std;
#define MAXN 400005
int n,m,x,y,z;
long long tree[MAXN],tt[MAXN],ans,su,aa[MAXN],c;
int lowbit(int i)
{
    return i&(-i);
}
void add(int i,long long x)
{
    long long zz=i;
    while(i<=MAXN)
    {
        tree[i]+=x;
        tt[i]+=x*zz;
        i+=lowbit(i);
    }
}
long long sum(int i)
{
    long long s=0;
    while(i>0)
    {
        s+=tree[i];
        i-=lowbit(i);

    }
    return s;
}
long long sum2(int i)
{
    long long s=0;
    while(i>0)
    {
        s+=tt[i];
        i-=lowbit(i);
    }
    return s;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&aa[i]);
        add(i,aa[i]);
    }
    while(m--)
    {
        scanf("%d%d%d",&x,&y,&z);
        if(x==1)
        {
            su=sum(z);
            ans=(su-sum(y-1))*(z-y+1)-(sum2(z)-sum2(y)-(su-sum(y))*y);
            printf("%lld\n",ans);
        }
        else if(x==2)
        {
            c=z;
            z=z-aa[y];
            aa[y]=c;
            add(y,z);
        }
    }
}

I、Characters with Hash

模拟

代码:

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
int main(){
    int T;
    int i,j,n;
    string ch1,ch2;
    cin>>T;
    while(T--){
        cin>>n;
        cin>>ch1;
        cin>>ch2;
        bool flag=0;
        for(i=0;i<n;i++){
            int temp=abs(ch2[i]-ch1[0]);
            if(temp==0){
                continue;
            }
            else if(temp<10){
                flag=1;
                j=i;
                break;
            }
            else{
                j=i;
                break;
            }
        }
        if(i==n&&flag==0){
            printf("1\n");
        }
        else{
            int ans=(n-j)*2;
            if (flag==1){
                cout<<ans-1<<endl;
            }
            else {
                cout<<ans<<endl;
            }
        }
    }
}

J、Maze Designer

LCA+最大树

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=500010;
int n,m,q,tot,tot2,cnt,tmp,ans,N;
int f[maxn][20];
int head[maxn];
ll dis[maxn];
int dfn[maxn],d[maxn];
int dep[maxn],e[maxn],pos[maxn],fa[maxn];
bool vis[maxn];
struct node
{
    int to,nex;
    ll w;
    bool operator<(node aa)const
    {
        return w>aa.w;
    }
}a[maxn],aa[maxn];
void add(int u,int v,ll w)
{
    a[cnt].to=v;
    a[cnt].w=w;
    a[cnt].nex=head[u];
    head[u]=cnt++;
}
void init()
{
    cnt=tot=tot2=0;
    memset(head,-1,sizeof(head));
    memset(pos,-1,sizeof(pos));
    memset(vis,0,sizeof(vis));
    memset(fa,-1,sizeof(fa));
    dis[1]=0;
}
void dfs(int u,int deep)//1
{
    if(pos[u]!=-1)return;
    dfn[tot2]=u;d[u]=tot2++;
    pos[u]=tot;e[tot]=u;dep[tot++]=deep;
    for(int i=head[u];i!=-1;i=a[i].nex)
    {
        int v=a[i].to;
        if(pos[v]==-1)
        {
            dis[v]=dis[u]+a[i].w;
            dfs(v,deep+1);
            e[tot]=u;dep[tot++]=deep;
        }
    }
}
void rmq(int n)//2
{
    for(int i=1;i<=n;i++)f[i][0]=i;
    for(int j=1;(1<<j)<=n;j++)
    for(int i=1;i+(1<<j)-1<=n;i++)
    {
        if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]) f[i][j]=f[i][j-1];
        else f[i][j]=f[i+(1<<(j-1))][j-1];
    }
}
int RMQ(int l,int r)
{
    int k=(int)(log((double)(r-l+1))/log(2.0));
    if(dep[f[l][k]]<dep[f[r-(1<<k)+1][k]]) return f[l][k];
    else return f[r-(1<<k)+1][k];
}
int lca(int x,int y)//3
{
    if(pos[x]<pos[y]) return e[RMQ(pos[x],pos[y])];
    else return e[RMQ(pos[y],pos[x])];
}
ll cal(int x,int y)
{
    return dis[x]+dis[y]-2*dis[lca(x,y)];
}
int get_id(int i,int j)
{
    return (i-1)*m+j;
}
int find(int x){return fa[x]==-1?x:fa[x]=find(fa[x]);}
int main()
{
    int T,cas=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        //scanf("%d %d",&n,&q);
        int tt=0;
        char cc[5],hh[5];
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            ll x,y;
            scanf("%s %lld %s %lld",cc,&x,hh,&y);
            //add(x,y,z);
            //add(y,x,z);
            if(cc[0]=='D')
            {
                aa[tt].to=get_id(i,j);
                aa[tt].nex=get_id(i+1,j);
                aa[tt++].w=x;
            }
            if(hh[0]=='R')
            {
                aa[tt].to=get_id(i,j);
                aa[tt].nex=get_id(i,j+1);
                aa[tt++].w=y;
            }
        }
        sort(aa,aa+tt);
        int opt=0;
        n=n*m;
        for(int i=0;i<tt&&opt<n-1;i++)
        {
            int u=aa[i].to;
            int v=aa[i].nex;
            int faa=find(u);
            int fbb=find(v);
            if(faa!=fbb)
            {
                add(u,v,(ll)1);
                add(v,u,(ll)1);
                fa[faa]=fbb;
                opt++;
                //cout<<u<<" "<<v<<endl;
            }
        }
        dfs(1,0);
        rmq(2*n-1);//4
        ll ans=0;
        scanf("%d",&q);
        while(q--)
        {
            int u,v,uu,vv;
            scanf("%d%d%d%d",&u,&v,&uu,&vv);
            ans=cal(get_id(u,v),get_id(uu,vv));
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值