14th.Feb.2019

T1


  • 今天的第一题是数据结构题,简单来说一下题意。规定:对于任意两个区间(l,r)和(a,b),如果l<a<r或l<b<r,那么区间(a,b)可以到达区间(l,r)。有n次操作,操作有两种:

    ​ 1、添加一个区间(数据保证添加的区间长度是单调递增的)

    ​ 2、给定区间编号x,y,询问x能否到y

  • 首先很明显的一点,如果区间(a,b)和区间(c,d)可以互相到达,那么两个区间可以合并成一个大区间,具体用并查集维护。
  • 由于所给出的区间的长度是递增的,所以对于一个区间(a,b)我们在线段树中对应节点插入它
  • 所有包含a或b的那些节点中的区间都可以与当前区间互达
  • 对于不可互达的那些区间,他们之间的连通关系可以看成是一个森林(每个子树都有个根,子节点可以走到父节点)
  • 找出询问的两个区间的根节点,之后直接判断即可
  • (代码后续会填坑img

T2


  • 第二题是思维难度题。并且数据范围很sb,只有一个n!复杂度的20分和O(n)的复杂度的100分,毒瘤!
  • 怎么写啊QAQ
  • 看了syq学长的博客,在代码、文字解释的帮助下,终于懂了。
  • 首先,置换和排列没啥区间,所以我们不做区分。一个排列是可以看做是有向图,比如当前排列里第i个数是x,就有一条有向边(i,x)。你发现所有的排列构成的有向图一定是由若干个环组成的。
  • 然后我们假设已经知道了答案要求的排列,建出了图。当你平方的时候,相当于x到y有一条路,y到z有一条路,然后平方之后是x到z有一条路。那么你发现,这时候平方之后状态的改变与环的奇偶性有关。
  • 如果是偶环,那么它会变成两个长度相等的环,两个环中的点是按照原来环的顺序依次一个个取出来的(就是你取一个我取一个这样)。
  • 如果是奇环,那么平方之后它仍然是奇环,不过是在图中移两步依次连接。
  • 所以知道该怎么做了吧?
  • 先把平方的置换p建成图,分出每一个环。如果存在某一个偶环找不到长度相等的环与之合并,就无解。
  • 有解的情况如何求出解呢?对于奇环,我们只需要根据刚才说的移两步性质,取答案的时候也移两步就好了。偶环呢?把两个长度相等的偶环左一个右一个地插入合并。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
vector<int>c[N];
int n,cnt,a[N],vis[N],ans[N],id[N];
inline int read(){
    char ch=getchar();int num=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){num=num*10+ch-'0';ch=getchar();}
    return num*f;
}
void dfs(int x){
    c[cnt].push_back(x);
    vis[x]=1;
    if(!vis[a[x]]) dfs(a[x]);
}
bool cmp(int a,int b){return c[a].size()<c[b].size();}
int main(){
    n=read();
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=1;i<=n;++i) if(!vis[i]) ++cnt,dfs(i);
    for(int i=1;i<=cnt;++i) id[i]=i;
    sort(id+1,id+cnt+1,cmp);
    for(int i=1;i<=cnt;++i){
        //奇环 
        if(c[id[i]].size()&1){
            int mid=c[id[i]].size()>>1;mid++;
            for(int j=0;j<c[id[i]].size();++j)
                ans[c[id[i]][j]]=c[id[i]][(j+mid)%c[id[i]].size()];
        }else{
            if(c[id[i+1]].size()!=c[id[i]].size()){
                printf("-1\n");
                return 0;
            }
            for(int j=0;j<c[id[i]].size();++j){
                ans[c[id[i]][j]]=c[id[i+1]][j];
                ans[c[id[i+1]][j]]=c[id[i]][(j+1)%c[id[i]].size()];
            }
            i++;
        }
    }
    for(int i=1;i<=n;++i) printf("%d ",ans[i]);
    return 0;
}

T3

这个不写吧,,,,真不会,很鬼畜的DP。

猜你喜欢

转载自www.cnblogs.com/kgxw0430/p/10380571.html