POI2010 题解整理

来源:互联网 发布:包头软件培训学校 编辑:程序博客网 时间:2024/05/22 20:07

官网链接:17th Polish Olympiad in Informatics

Guilds

Description

Zy皇帝面临一个严峻的问题,两个互相抵触的贸易团体,YYD工会和FSR工会,他们在同一时间请求在王国各个城市开办自己的办事处。

这里有n个城市,其中有一些以双向马路相连,这两个工会要求每个城市应该做到:

  • 有这个工会的办事处或
  • 和另外一个符合1条件的城市有马路直接相连。

也就是每个城市必须是YYD的公会,但是又和FSR的公会的城市相连,或者是FSR的,和YYD的城市相连,或者和两个工会的城市相连。

但是Zy怀疑不正当的竞争,他担心一个城市有两个工会的办事处,(就是说一个城市不能有两个工会的办事处)只将导致贸易的垄断,所以他请求他日夜栽培的你给予帮助。

贪心题。

对于一条边的两个端点,显然是可以满足题意的,只需要各选一点建不同的公会即可。显然这个思路能够扩展到整个连通块的情况,因为题意只需要满足有两种颜色能够覆盖到它。当某点染成A时,必然有一直接相连的点是可以染成B色,而且不会影响题意。

那么对于上述结论的唯一反例就是孤立点。若该图中存在孤立点,那么就不能满足题意。


Railway

题解讲的很清楚了。显然不能直接构边,于是有直接维护当前两个栈内状态的解法1和构建对应关系作为边的解法2。


Beads

Hash水题,唯一关键点是调和级数对复杂度的贡献问题。(最近的Codeforces376就考到过调和级数优化算法的题目)


Divine Divisor

模拟题。关键点在于伪素数判定算法Miller_Rabin,参考Matrix67大犇的讲解。


Intelligence Test

Description

给定原序列和多个新的序列,判断该序列是否是原序列的子序列

数据范围有点大所以比较虚。对于当前的元素,我们只需要找到在满足前面序列后,在原序列中出现的最近位置(即该序列前面部分最少也要到pos的位置,那么下一个元素就必须要在[pos+1,n]的范围内找)。

预处理出所有相同的元素的位置,枚举可以采用二分去找。


Antisymmetry

裸的最大回文串判定题,O(nlogn)算法可以采用二分+Hash的做法(实际上到这步已经足够),O(n)的算法详见Manacher算法(个人感觉有些过时)。


Hamsters

除了优化一般高复杂度的字符串前后缀匹配算法,最重要的就是倍增Floyd算法(亦可以联系到矩阵,两者均满足无后向性)(倍增法的一个运用)。


Blocks

本题重点在于对题意进行的转化。然后就是单调栈O(nlogn)裸题,根据单调性与最优性还可以进一步优化到O(n)平摊复杂度转移。


Sheep

计算几何裸题。为了有序处理出符合题意的边,需要进行极角排序。之后的dp非常经典,是Catalan数的基本递推公式。


Teleportation

yy题。根据题意进行分层即可。


Monotonicity

在不证明dp命题的情况下本题是数据结构+dp裸题。本题重点在于证明。


The Minima Game

带博弈色彩的一道裸dp,比较玄学。


Lamp

应该是一道三维计算几何题,不会写留坑。


Frog

Description

一条无限宽的河,上有n(n106)块石头,石头离左边的河岸(右边河岸无限远)距离严格递增。现在小C任选一块石头开始跳,他只会跳到第k(kn)远的石头上(假如不是唯一的就跳到离岸最近的石头上),求他对于每块石头,跳了m(m1018)次之后所在的位置。

可以发现每块石头的第k远是唯一的,这个部分可以通过O(n)尺取法求得。同理,每块石头开始,跳2d次的第k远也是唯一的,所以我们考虑倍增法进行跳跃。加上滚动数组优化后,空间复杂度也能大幅度缩小了。

#include <bits/stdc++.h>#define M 1000005#define S 60using namespace std;typedef long long ll;ll res[M];int son[2][M],pos[M];int main(){    int n,K;ll step;    scanf("%d %d %lld",&n,&K,&step);    for(int i=1;i<=n;i++)scanf("%lld",&res[i]);    int L=1,R=K+1;    for(int i=1;i<=n;i++){        do ++R;        while(R<=n&&res[i]-res[L]>=res[R]-res[i]);--R;        while(R-L>K)//最后R-L==K            if(res[i]-res[L]>res[R]-res[i])++L;            else --R;        if(res[i]-res[L]>=res[R]-res[i])son[0][i]=L;        else son[0][i]=R;       }    for(int i=1;i<=n;i++)pos[i]=i;    for(int j=0;j<=S;j++){        int cur=j&1;        if(step>>j&1)for(int i=1;i<=n;i++)pos[i]=son[cur][pos[i]];        for(int i=1;i<=n;i++)            son[cur^1][i]=son[cur][son[cur][i]];    }    for(int i=1;i<=n;i++)printf("%d%c",pos[i],i==n?'\n':' ');    return 0;}

Ones

魔性的数论题,不会写留坑。


Bridges

图论题,核心算法是混合图欧拉回路判定与欧拉回路路径输出。


Pilots

滑动窗口。需要用单调队列同时维护一段区间内的最值。

转移比较麻烦,时间复杂度为O(n)

#include<bits/stdc++.h>#define M 3000005using namespace std;inline void Rd(int &res){    res=0;char c;    while(c=getchar(),c<48);    do res=(res<<3)+(res<<1)+(c^48);    while(c=getchar(),c>47);}int A[M];int deqmi[M],Lmi=0,Rmi=-1;int deqmx[M],Lmx=0,Rmx=-1;int work(int K,int n){    int len=1;    deqmi[++Rmi]=1,deqmx[++Rmx]=1;    for(int i=1,p;i+len-1<=n;i++){        while(p=i+len,p<=n)            if(max(A[p],A[deqmx[Lmx]])-min(A[p],A[deqmi[Lmi]])<=K){                while(Lmx<=Rmx&&A[deqmx[Rmx]]<=A[p])--Rmx;deqmx[++Rmx]=p;                while(Lmi<=Rmi&&A[deqmi[Rmi]]>=A[p])--Rmi;deqmi[++Rmi]=p;                ++len;            }else break;        if(i+len>n)break;        while(Lmx<=Rmx&&A[deqmx[Rmx]]<=A[p])--Rmx;deqmx[++Rmx]=p;        while(Lmi<=Rmi&&A[deqmi[Rmi]]>=A[p])--Rmi;deqmi[++Rmi]=p;//向后移动的时候没有考虑i+len那个         while(Lmx<=Rmx&&deqmx[Lmx]<=i)++Lmx;        while(Lmi<=Rmi&&deqmi[Lmi]<=i)++Lmi;//      printf("%d %d\n",A[deqmx[Rmx]],A[deqmi[Rmi]]);//    }    return len;}int main(){     int K,n;Rd(K),Rd(n);     for(int i=1;i<=n;i++)Rd(A[i]);     printf("%d\n",work(K,n));}

对于POI2010的这组题:

  • 倍增法:Hamsters,Frog
  • Hash运用:Beads,Antisymmetry,Hamsters
  • 图论:Railway,Bridges
  • 数论:Beads,Divine Divisor,Sheep
  • yy题:Teleportation,Monotonicity,The Minima Game
  • 尺取法(尺取都是玄学):Flog,Pilots
0 0
原创粉丝点击