• 1012


    期望得分 200
    实际得分 174
    话说这个第三题sub都没有... 不好骗分啊
    A 排 座位
    ( ( arrange .pas/c/cpp)
    【问题描述】
    信竞队有 n 名队员,竞赛机房有一张长桌,上面一字排开有 n 台电脑,供同学们坐成一
    排使用。每学期开始前,老师都要给同学们排座位。
    同学之间存在仰慕(膜拜)关系,如 A 同学仰慕 B 同学,那么 A 同学就要求座位必须与 B
    同学相邻。同学之间存在 m 对仰慕关系。老师想要找到使得所有同学的要求都得到满足座位
    安排方案。请你帮忙计算合法方案的总数,答案可能很大,mod 989999 后再输出。

    主要说一下判环的问题
    首先注意到一条边的环只用在读入的时候判断一下就行了
    然后对于环不是一条边的情况 我们只需要在加进集合里的时候判断是不是在一个集合就行了
    也可以用top排序求环

    //
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define  mod 989999
    #define maxnn 1000010
    typedef pair<int,int > P;
    map<P,int > mm;
    ll n,m;
    int r[maxnn];
    int f[maxnn];
    int ru[maxnn];
    ll cnt1=1,cnt2;
    ll size[maxnn];
    #define GC getchar()
    inline ll R()
    {
    	char t;
    	ll f=1;
    	ll x=0;
    	t=GC;
    	while(!isdigit(t)) {if(t=='-') f=-1;t=GC;}
    	while(isdigit(t)) 
    	{
    		x=x*10+t-'0';
    		t=GC;
    	}
    	return x*f;
    }
    int gf(int v)
    {
        return f[v]==v?v:f[v]=gf(f[v]);
    }
    ll jie(ll v)
    {
        ll tmp=1;
        for(int i=1;i<=v;i++)
        {
            tmp=(tmp*i)%mod;
        }
        return tmp%mod;
    }
    void FIE()
    {
        freopen("arrange.in","r",stdin);
        freopen("arrange.out","w",stdout);
    }
    int main()
    {
        //FIE();
       	n=R();
       	m=R();
        ll x,y;
        for(int i=1;i<=n;i++)
        {
            f[i]=i;
            size[i]=1;
        }
        for(int i=1;i<=m;i++)
        {
            x=R();
            r[x]=R();
            int y=r[x];
            if(r[r[x]]==x) continue;
            ru[y]++;
            ru[x]++;
            if(ru[x]>2||ru[y]>2) 
            {
            	puts("0");
            	return 0;
            }
            int fx=gf(x);
            int fy=gf(y);
            if(fx!=fy)
            {
                size[fy]+=size[fx];
                f[fx]=fy;
            }
            else
            {
            	puts("0");
            	return 0;
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(f[i]==i)
            {
                if(size[i]>1) cnt1=(cnt1*2)%mod;;
                cnt2++;
            }
        }    
        cout<<(jie(cnt2)*cnt1)%mod;
     } 
    

    B 数列截段
    时间限制 : - MS 空间限制 : - KB
    评测说明 : 1s,256m
    问题描述
    老师给出一个长度为N的整数数列A。现在要求你在A中截取一段连续子序列,使得该区间的数字总和不小于X,并且不大于Y。问总共有多少种不同的截取方式?

    想到用前缀和+树状数组离散化
    式子可以表示为 x<=sum[j]-sum[i-1]<=y
    先求x<=sum[j]-sum[i-1] 然后容斥一下减去y<sum[j]-sum[i-1]的方案之和即为答案
    code:

    //
    #include<bits/stdc++.h>
    using namespace std;
    #define maxnn 500000
    #define ll long long 
    #define lowbit(i) i&(-i)
    ll sum[maxnn];
    ll n,x,y;
    int id[maxnn];
    ll zh[maxnn];
    ll c[maxnn];
    ll tr=0;
    #define GC getchar()
    inline ll R()
    {
    	char t;
    	ll f=1;
    	ll x=0;
    	t=GC;
    	while(!isdigit(t)) {if(t=='-') f=-1;t=GC;}
    	while(isdigit(t)) 
    	{
    		x=x*10+t-'0';
    		t=GC;
    	}
    	return x*f;
    }
    void add(int x)
    {
        for(int i=x;i<=3*n+100000;i+=lowbit(i))
        {
            c[i]++;
        }
    }
    ll get(int x)
    {
        ll ans=0;
        for(int i=x;i;i-=lowbit(i))
        {
            ans+=c[i];
        }
        return ans;
    }
    void FIE()
    {
        freopen("cutout.in","r",stdin);
        freopen("cutout.out","w",stdout);
    }
    int main()
    {
       	//FIE();
        ll t=0;
        ll ans=0;
        n=R();
        x=R();
        y=R();
        for(int i=1;i<=n;i++)
        {
            t=R();
            sum[i]=sum[i-1]+t;
            tr++;
            sum[n+tr]=sum[i]-x;
            tr++;
            sum[n+tr]=sum[i]-y;
            zh[i]=sum[i];
        }
        sort(sum,sum+1+n+tr);
        int r=unique(sum,sum+1+n+tr)-sum-1;
        for(int i=0;i<=n;i++)
        {
            id[i]=lower_bound(sum,sum+1+r,zh[i])-sum+1;
        }
        for(int i=0;i<=n;i++)
        {
            ll tmp1=lower_bound(sum,sum+1+r,zh[i]-x)-sum+1;
            ans+=get(tmp1);
            ll tmp2=lower_bound(sum,sum+1+r,zh[i]-y)-sum+1;
            ans=ans-get(tmp2-1);
            add(id[i]);
        }
        printf("%lld",ans);
    }
    

    C 水壶

    JOI君所居住的IOI市以一年四季都十分炎热著称。
    IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物、原野、墙壁之一。建筑物的区域有P个,编号为1...P。
    JOI君只能进入建筑物与原野,而且每次只能走到相邻的区域中,且不能移动到市外。
    JOI君因为各种各样的事情,必须在各个建筑物之间往返。虽然建筑物中的冷气设备非常好,但原野上的日光十分强烈,因此在原野上每走过一个区域都需要1单位的水。此外,原野上没有诸如自动售货机、饮水处之类的东西,因此IOI市的市民一般都携带水壶出行。大小为x的水壶最多可以装x单位的水,建筑物里有自来水可以将水壶装满。
    由于携带大水壶是一件很困难的事情,因此JOI君决定携带尽量小的水壶移动。因此,为了随时能在建筑物之间移动,请你帮他写一个程序来计算最少需要多大的水壶。
    现在给出IOI市的地图和Q个询问,第i个询问(1<=i<=Q)为“在建筑物Si和Ti之间移动,最小需要多大的水壶?”,请你对于每个询问输出对应的答案。

    解:

    复习点:BFS+最小生成树+倍增LCA

    一眼货车运输的既视感,然而需要先知道两个点之间的距离。

    好在这种网格图是可以BFS的,所以把每个建筑物压到队列中,跑BFS,记录每个点被哪个点所搜到,以及与搜到点的距离是多少。

    当搜到另一个被其它点搜到过的点时,将它们被搜到的建筑物之间连边,这样边集只有O(4wh)。然后跑Kruskal。

    (这里需要注意的是直接将这两个点在并查集中合并是不行的,因为搜到的不一定是最短距离;而按照距离排序搜索也是不对的。必须把所有可能的边连上跑最小生成树才可行。)

    这个过程中可以按照距离将所有的边放到类似于桶的东西中,形成若干个链表(或者使用vector),这样能够省去排序的过程。

    然后get到最小生成树之后跑倍增LCA即可。注意跑LCA时求的答案是路径最大值,不是最小值。

    另外,本题不仅仅是一棵树,可能是森林,所以需要把每棵树都遍历一遍。别忘判断-1的情况。

    时间复杂度O(wh+mlogn)

    一句话题解
    BFS连边求网格图最短路
    kruskal跑最小瓶颈森林 保证所有的树都满足题目条件
    无根树转有根树 倍增求LCA

    code:

    //
    #include<stdio.h>
    #include<bits/stdc++.h>
    using namespace std;
    #define maxnn 2005
    int n,m,q,p;
    char ch[maxnn];
    bool mapp[maxnn][maxnn];
    int las[maxnn][maxnn];
    int dis[maxnn][maxnn];
    int f[200010];
    int ff[200010][19];
    int deep[200010];
    int lass[400010],en[400010],le[400010],nex[400010],tot;
    int fff[200010][19];
    void add(int a,int b,int c)
    {
        en[++tot]=b;
        nex[tot]=lass[a];
        lass[a]=tot;
        le[tot]=c;
    }
    struct node
    {
        int st,en,le;
        
    }ed[4000100];
    int in=0;
    typedef pair<int ,int > P;
    bool cmp(node a,node b){
        return a.le<b.le;
    }
    queue<P > Q;
    int dx[5]={1,-1,0,0};
    int dy[6]={0,0,1,-1};
    void bfs()
    {
        while(Q.size())
        {
            P s=Q.front();Q.pop();
            for(int i=0;i<=3;i++)
            {
                int tmp1=dx[i]+s.first;
                int tmp2=dy[i]+s.second;
                if(tmp1>=1&&tmp2>=1&&tmp2<=m&&tmp1<=n)
                {
                    if(mapp[tmp1][tmp2]==true) continue;
                    if((las[tmp1][tmp2]!=las[s.first][s.second])&&(las[tmp1][tmp2]))
                    {
                        ed[++in]=node{las[tmp1][tmp2],las[s.first][s.second],dis[s.first][s.second]+dis[tmp1][tmp2]};
                    }
                    else
                    if(!dis[tmp1][tmp2])
                    {
                        dis[tmp1][tmp2]=dis[s.first][s.second]+1;
                        las[tmp1][tmp2]=las[s.first][s.second];
                        Q.push(make_pair(tmp1,tmp2));
                    }
                }
            }
        }
        
    }
    int gff(int v)
    {
        return f[v]==v?v:f[v]=gff(f[v]);
    }
    void  gf(int v){
        int x=ed[v].st;
        int y=ed[v].en;
        int fx=gff(x);
        int fy=gff(y);
        if(fx==fy) return ;
        f[fx]=fy;
        add(x,y,ed[v].le);
        add(y,x,ed[v].le);
    }
    void dfs(int v,int fa)
    {
        fff[v][0]=fa;
        deep[v]=deep[fa]+1;
        int d=log2(p+1000);
        for(int i=1;i<=d;i++)
        {
            fff[v][i]=fff[fff[v][i-1]][i-1];
            ff[v][i]=max(ff[v][i-1],ff[fff[v][i-1]][i-1]);
        }
        for(int i=lass[v];i;i=nex[i])
        {
            int u=en[i];
            if(u!=fa)
            {
                ff[u][0]=le[i];
                dfs(u,v);
            }
        }
    }
    int go_up(int s,int k)
    {
        int d=log2(p+1000);
        for(int i=d;i>=0;i--)
        {
            if(k&(1<<i))
            {
                s=fff[s][i];
            }
        }
        return s;
    }
    int getlca(int x,int y)
    {
        int tmp=0;
        if(deep[x]<deep[y]) swap(x,y);
        int d=x;
        x=go_up(x,deep[x]-deep[y]);
        int k=deep[d]-deep[y];
        {
            int s=log2(p+1000);
            for(int i=s;i>=0;i--)
            {
                if(k&(1<<i))
                {
                    tmp=max(ff[d][i],tmp);
                    d=fff[d][i];
                }
            }
           
        }
        if(x==y) return tmp;
        int s=log2(p+1000);
        for(int i=s;i>=0;i--)
        {
            if(fff[x][i]!=fff[y][i])
            {
                tmp=max(ff[x][i],tmp);
                tmp=max(ff[y][i],tmp);
                x=fff[x][i];
                y=fff[y][i];
            }
        }
        tmp=max(tmp,ff[x][0]);
        tmp=max(tmp,ff[y][0]);
        return tmp;
    }
    void FIE()
    {
        freopen("kettle.in","r",stdin);
        freopen("tesss","w",stdout);
    }
    int main()
    {
        //FIE();
        scanf("%d%d%d%d",&n,&m,&p,&q);
        for(int i=1;i<=p;i++)
        {
            f[i]=i;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ch+1);
            for(int j=1;j<=m;j++)
            {
                if(ch[j]=='#')
                {
                    mapp[i][j]=true;
                }
            }
        }
        int x1,y1;
        int x,y;
        for(int i=1;i<=p;i++)
        {
            scanf("%d%d",&x1,&y1);
            las[x1][y1]=i;
            dis[x1][y1]=0;
            Q.push(make_pair(x1,y1));
        }
        bfs();
        sort(ed+1,ed+1+in,cmp);
        for(int i=1;i<=in;i++)
        {
            gf(i);
        }
        for(int i=1;i<=p;i++)
        {
            if(f[i]==i)
            {
                dfs(i,i);
            }
        }
        while(q--)
        {
            scanf("%d%d",&x,&y);
            if(gff(x)!=gff(y))
            {
                puts("-1");
            }
            else
            {
                printf("%d
    ",getlca(x,y));
            }
    	}
    }
    
  • 相关阅读:
    Eclipse汉化后怎么改回英文版 (中文 改 英文)
    解决android中Layout文件下的xml文件配好后,R类中不能自动生成相应代码
    Android SDK离线安装
    Windows环境下Android Studio v1.0安装教程
    Eclipse调试Bug的七种常用技巧
    博客开通了
    Android常见的按钮监听器实现方式
    用setTimeout实现在DOM上(通常是菜单栏)鼠标停留一段时间才执行相应的操作
    Javascript模块模式学习分享
    Oracle数据库逻辑存储结构管理
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11665890.html
Copyright © 2020-2023  润新知