USACO DEC17,Platinum

        第一次打usaco,感觉题目还挺有趣的。(为啥感觉美国人的英语比日、俄的英语还要难读呢)


Standinfg Out from the Herd.

        题意:给n个字符串,对每个字符串求有多少本质不同的子串只在这个字符串中出现。

        这题我直接求了一个广义后缀自动机,然后给每个点一个标记表示这个点对应的子串是否只在某个字符串中出现。然后随便统计一下就做完了。O(N)。

AC代码如下:

#include
#define N 200009
using namespace std;

int n; long long ans[N]; char s[N];
struct sam{
	int tot,fst[N],nxt[N],ch[N][26],fa[N],len[N],f[N];
	sam(){ tot=1; }
	void calc(int x,int y){ f[x]=(f[x] && f[x]!=y?-1:y); }
	int add(int k,int c,int p){
		int np=++tot; calc(np,k); len[np]=len[p]+1;
		for (; p && !ch[p][c]; p=fa[p]) ch[p][c]=np;
		if (!p){
			fa[np]=1; return np;
		}
		int q=ch[p][c];
		//cerr<<"	"<



Push a Box

        题意:有障碍的地图上一个人推一个箱子,多次询问箱子最后能否到达目的地。

        显然要预处理全部的答案,然后每次O(1)询问。考虑用f[i][j][k]表示箱子在i,j,人在箱子的k方向上能否到达。有两种转移,分别是推一步箱子和改变人的位置。能够改变人的位置当且仅当两个点在同一个点双。

AC代码如下:

#include
#define N 2009
#define M 2500009
#define E 10000009
using namespace std;

int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
int m,n,cas,dfsclk,tot=1,cnt,tp,pt,p[N][N],px[M],py[M];
int fst[M],pnt[E],nxt[E],dfn[M],low[M],q[M],fa[M<<1];
char s[N][N]; bool ans[N][N][4],vis[N][N];
struct node{ int x,y,k; }h[M];
void add(int x,int y){
    if (!x || !y) return;
    pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
void dfs(int x,int p){
    int i,y; dfn[x]=low[x]=++dfsclk; q[++tp]=x;
    for (i=fst[x]; i; i=nxt[i]) if (i!=(p^1)){
        y=pnt[i];
        if (!dfn[y]){
            dfs(y,i); low[x]=min(low[x],low[y]);
	        if (low[y]==dfn[x]){
	            for (pt++; q[tp]!=y; tp--){
	                fa[q[tp]]=pt;
	            }
				fa[q[tp--]]=pt; fa[pt]=x;
	        } else if (low[y]>dfn[x]){
				while (q[tp]!=y) tp--; tp--;
			}
        } else low[x]=min(low[x],dfn[y]);
    }
}
bool check(int x,int y){
    if (!x || !y) return 0;
	//cerr<<"check: "<


Greedy Gift Takers
        题意:有n头奶牛,每头奶牛有一个数值a[i],表示当这个奶牛在首位的时候,它会跑到倒数第a[i]+1位上。问有多少头奶牛永远不能到首位。

        首先令a[i]=n-a[i]。考虑如果a[1]=1,那么显然答案为n-1。进一步发现如果存在一个大小为M的集合{x1,...,xM},满足x1<...

AC代码如下:

#include
#define N 100009
using namespace std;

int n,m,a[N];
priority_queue Q;
bool check(int x){
	int i;
	while (!Q.empty()) Q.pop();
	for (i=1; i<=x; i++) Q.push(n-a[i]);
	for (; !Q.empty() && Q.top()>x; Q.pop()) x--;
	return x>0;
}
int main(){
	freopen("greedy.in","r",stdin); freopen("greedy.out","w",stdout);
	scanf("%d",&n);
	int i;
	for (i=1; i<=n; i++) scanf("%d",&a[i]);
	int l=1,r=n,mid;
	while (l>1;
		if (check(mid)) r=mid; else l=mid+1;
	}
	printf("%d\n",n-l);
	return 0;
}

by lych

2017.12.23

你可能感兴趣的:(usaco,比赛,后缀自动机,图论,点双连通分量,二分,贪心)