12.6英语专场

UVA - 11604 General Sultan

题意
This is war time again! Our beloved Sultan has assumed the post of a general and going to the war with his huge army. Being an intelligent fellow as he is, he has discovered a handful of new weapons to help him win the war. In order to facilitate instructing his units, he assigns each type of weapon a single binary code. For example, he has three types of weapons
FordCannon (code: 1)
EdmondMortar (code: 10)
HopcroftRi e (code: 00)
So, now when he makes one long beep and one short beep (that is,10) from his grand whistle, an EdmondMortar unit is red while when he makes two short beeps means, 00 ), a HopcroftRi e comes into action. Please note that, he has an unlimited supply of every types.Problem arised when in an war, the units were coded like
FordCannon (01),
EdmondMortar (001),
HopcroftRi e (01001).
Once, he went for a HopcroftRi e (01001) but his men red a FordCannon (01) and then an EdmondMortar (001) instead. The furious Sultan realized that the coding itself was ambigous i.e. more than one sequence of the weapons can translate into the same signal. Now, your task is to determine if a given coding scheme is ambiguous or not before the war starts.

Input
There will be around 100 test cases. Every test case starts with a single integer
N:(1<=N<=100), the number of weapon types. Each of the following N lines contains a string (denoting the name of the
weapon, less than 21 characters) and a binary number (the code, less than 21 characters).
The last test case will be followed by a single ‘0’.

Output
For every test case, print ‘Case #x:’, where x is the case number. Then print ‘Ambiguous.’ if a code leads to multiple sequences or print ‘Not ambiguous.’ otherwise.

Sample Input
3
FordCannon 1
EdmondMortar 10
HopcroftRifle 00
3
FordCannon 01
EdmondMortar 001
HopcroftRifle 01001
0

Sample Output
Case #1: Not ambiguous.
Case #2: Ambiguous.

有道翻译给出的人话

这是战争一次又一次!我们亲爱的苏丹认为一般的帖子,将战争与他的巨大的军队。作为一个聪明的家伙,因为他是,他发现了一把新武器,帮助他赢得了战争。他为了方便指导单位,分配每种类型的武器一个单一的二进制代码。例如,他有三个类型的武器
FordCannon(代码:1)
EdmondMortar(代码:10)
HopcroftRi e(代码:00)
现在当他使一个长音短beep(10)从他大吹口哨,一个EdmondMortar单位是红色,而当他犯了两个短的哔哔声,00),HopcroftRi e进入行动。请注意,他有无限供应的每一个类型。问题出现在一个战争,单位编码
FordCannon(01),
EdmondMortar(001),
HopcroftRi e(01001)。
有一次,他去HopcroftRi e(01001),但他的人红FordCannon(01),然后一个EdmondMortar(001)。愤怒的苏丹意识到编码本身是ambigous即多个序列的武器可以转化为相同的信号。现在,你的任务是确定一个给定的编码方案在战争开始之前是否模糊。

输入
将会有大约100个测试用例。每个测试用例都始于一个整数
N:(1 < = N < = 100),武器类型的数量。每个下面的N行包含一个字符串(表示的名称
武器,小于21个字符)和一个二进制数(代码,少于21个字符)。
最后一个测试用例之后,随之而来的将是一个“0”。

输出
为每个测试用例,打印“案例# x:”,其中x是数量。然后打印的模棱两可。如果一个代码导致多个序列或打印的不模糊。否则。

做法

从两个串开始,不停的按照前缀后缀匹配 ,最后达到两个方案同时在一个点结束,则此方案为所求方案 。

枚举a串从h开始的后缀和b串的前缀匹配,看是否能将其中一个串匹配完 。问题转化为 :从某个串的第一个点开始走到终点。

才知道字符串匹配可以建图dfs做的,长姿势了。

代码如下

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int M=2505;
int cas,n,m,i,j,k,l,p,f,tot;
char s[M][25];
int to[M*100],he[M*100],ne[M*100],v[M],len[M],id[M][25];
void add(int u,int v){
    to[++tot]=v;ne[tot]=he[u];he[u]=tot;
}
void dfs(int x){
    if(x==p){f=1;return;}
    v[x]=1;int i,y;
    for(i=he[x];i;i=ne[i]){
        y=to[i];
        if(!v[y]) dfs(y);
        if(f) return;
    }
}
int main(){
    //freopen("out.out","w",stdout);
    for(;scanf("%d",&n)!=EOF&&n!=0;){
        for(i=k=1;i<=n;++i){
            scanf("%s%s",s[i]+1,s[i]+1);
            len[i]=strlen(s[i]+1);
            for(j=1;j<=len[i];++j) id[i][j]=k++;
        }for(tot=0,p=k,memset(he,-1,sizeof he),i=1;i<=n;++i)
            for(l=1;l<=len[i];++l)
            for(j=1;j<=n;++j){
                if(i==j&&l==1) continue;
                for(k=1;k<=len[j]&&l+k-1<=len[i];++k)
                    if(s[i][l+k-1]!=s[j][k]) break;
                if(k>len[j]&&l+k-1>len[i]) add(id[i][l],p);
                else if(k>len[j]) add(id[i][l],id[i][l+k-1]);
                else if(l+k-1>len[i]) add(id[i][l],id[j][k]);
            }for(f=0,memset(v,0,sizeof v),i=1;i<=n;++i){
                if(!v[id[i][1]]) dfs(id[i][1]);
                if(f) break;
            }printf("Case #%d: ",++cas);
            if(f) printf("Ambiguous.\n");
            else printf("Not ambiguous.\n");
    }
}

HDU3686

Problem Description

City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, the mayor plans to build a RTQS (Real Time Query System) to monitor all traffic situations. City C is made up of N crossings and M roads, and each road connects two crossings. All roads are bidirectional. One of the important tasks of RTQS is to answer some queries about route-choice problem. Specifically, the task is to find the crossings which a driver MUST pass when he is driving from one given road to another given road.

Input

There are multiple test cases.
For each test case:
The first line contains two integers N and M, representing the number of the crossings and roads.
The next M lines describe the roads. In those M lines, the ith line (i starts from 1)contains two integers Xi and Yi, representing that roadi connects crossing Xi and Yi (Xi≠Yi).
The following line contains a single integer Q, representing the number of RTQs.
Then Q lines follows, each describing a RTQ by two integers S and T(S≠T) meaning that a driver is now driving on the roads and he wants to reach roadt . It will be always at least one way from roads to roadt.
The input ends with a line of “0 0”.
Please note that: 0

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#define C(a,b) memset(a,b,sizeof a)
using namespace std;
const int M=100010;
int n,m,i,j,q,x,y,dfsx;
int to[M<<1],he[M],ne[M<<1],tot;
int To[M<<1],He[M],Ne[M<<1],Tot;
int dep[M],sz[M],fa[M],son[M],top[M];
stack<int> s;
//int st[M],tp;
int dfn[M],low[M],v[M],bl[M],ct[M],BLK,cut[M];
void add(int x,int y){
    to[++tot]=y;ne[tot]=he[x];he[x]=tot;
}
void ins(int x,int y){
    To[++Tot]=y;Ne[Tot]=He[x];He[x]=Tot;
}
void tarjan(int x,int fa){
    dfn[x]=low[x]=++dfsx;int blk=0;
    for(int i=he[x];i;i=ne[i]){
        int y=to[i];
        if(v[i]) continue;
        v[i]=v[i^1]=1;
        s.push(i);
        //st[++tp]=i;
        if(!dfn[y]){
            ++blk;tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if(dfn[x]<=low[y])
                for(ct[x]=1,++BLK;;){
                    //int tmp=st[tp--];
                    int tmp=s.top();s.pop();
                    bl[tmp]=bl[tmp^1]=BLK;
                    if(tmp==i) break;
                }
        }else low[x]=min(low[x],dfn[y]);
        //printf("low[%d]:%d\n",x,low[x]);
    }if(fa<0&&blk==1) ct[x]=0;
}
void dfs(int x){
    sz[x]=1;
    for(int y,i=He[x];i;i=Ne[i])
        if((y=To[i])!=fa[x]){
            fa[y]=x;dep[y]=dep[x]+1;
            //printf("x:%d y:%d\n",x,y);
            //system("pause");
            dfs(y);sz[x]+=sz[y];
            if(sz[y]>sz[son[x]]) son[x]=y;
        }
}
void dfs2(int x,int chain){
    top[x]=chain;
    if(son[x]) dfs2(son[x],chain);
    for(int y,i=He[x];i;i=Ne[i])
        if((y=To[i])!=son[x]&&y!=fa[x])
            dfs2(y,y);
}
int lca(int x,int y){
    for(;top[x]!=top[y];x=fa[top[x]])
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
    return dep[x]<dep[y]?x:y;
}
void bd(){
    int i;
    for(i=1;i<=n;++i)
        if(!dfn[i]) tarjan(i,-1);
    for(i=1;i<=n;++i)
        if(ct[i]) cut[i]=++BLK;
    for(i=1;i<=tot;++i){
        int y=to[i];
        if(!ct[y]) continue;
        ins(cut[y],bl[i]);ins(bl[i],cut[y]);
    }dfs(1);dfs2(1,1);
}
int main(){
    for(;scanf("%d%d",&n,&m)!=EOF&&n!=0&&m!=0;){
        for(i=1;i<=M-10;++i)
            he[i]=He[i]=0,
            dep[i]=sz[i]=fa[i]=son[i]=top[i]=0,
            dfn[i]=low[i]=v[i]=bl[i]=ct[i]=0,
            cut[i]=tot=Tot=BLK=dfsx=0;
        for(;!s.empty();s.pop());
        for(i=1;i<=m;++i)
            scanf("%d%d",&x,&y),add(x,y),add(y,x);
        for(bd(),scanf("%d",&q);q--;){
            scanf("%d%d",&x,&y);
            x--;y--;
            x=bl[x*2];y=bl[y*2];
            int LCA=lca(x,y);
            //printf("x:%d y:%d LCA:%d\n",x,y,LCA);
            printf("%d\n",(dep[x]+dep[y]-2*dep[LCA])/2);
        }
    }return 0;
}

Building Fire Stations

描述

ZOJ Problem Set - 3820
Building Fire Stations
Time Limit: 5 Seconds Memory Limit: 131072 KB Special Judge

Marjar University is a beautiful and peaceful place. There are N buildings and N - 1 bidirectional roads in the campus. These buildings are connected by roads in such a way that there is exactly one path between any two buildings. By coincidence, the length of each road is 1 unit.

To ensure the campus security, Edward, the headmaster of Marjar University, plans to setup two fire stations in two different buildings so that firefighters are able to arrive at the scene of the fire as soon as possible whenever fires occur. That means the longest distance between a building and its nearest fire station should be as short as possible.

As a clever and diligent student in Marjar University, you are asked to write a program to complete the plan. Please find out two proper buildings to setup the fire stations.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains an integer N (2 <= N <= 200000).

For the next N - 1 lines, each line contains two integers Xi and Yi. That means there is a road connecting building Xi and building Yi (indexes are 1-based).

Output

For each test case, output three integers. The first one is the minimal longest distance between a building and its nearest fire station. The next two integers are the indexes of the two buildings selected to build the fire stations.

If there are multiple solutions, any one will be acceptable.

Sample Input

2
4
1 2
1 3
1 4
5
1 2
2 3
3 4
4 5

Sample Out

1 1 2
1 2 4

人话

就是在一棵树里找两个点,使得所有点到这两个点中任意一个距离的最大值最小

做法

一种做法是求两边树的直径。第一遍求出来以后把树从重心处割断,对两棵树分别求重心,这两个重心就是所求点。

另一种更为简便的做法就是二分枚举答案,枚举到第一个点时bfs往下搜,直到枚举答案的最远点再进行bfs,搜遍所有点,最后扫一下所有点的距离即可。

二分代码如下

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int M=200010,inf=0x3f3f3f3f;
int n,m,i,j,a,b,u,v,T,l,r;
int d[M],pre[M],q[M],h,t;
vector<int> g[M];
int bfs(int x){
    for(h=t=d[x]=pre[x]=0,q[h]=x;h<=t;)
        for(x=q[h++],i=0;i<g[x].size();++i)
            if(d[g[x][i]]>d[x]+1)
                d[g[x][i]]=d[x]+1,pre[g[x][i]]=x,q[++t]=g[x][i];
    return x;
}
bool ok(int x){
    if(!x) if(n<=2) return 1;
           else return 0;
    for(int i=1;i<=n;++i) d[i]=inf;
    a=bfs(1);
    for(int i=0;i<x;++i){
        if(pre[a]==0){
            b=a%n+1;return 1;
        }a=pre[a];
    }for(int i=1;i<=n;++i) d[i]=inf;
    b=bfs(a);
    for(int i=0;i<x;++i){
        if(pre[b]==0){
            if(a==b) b=a%n+1;
            return 1;
        }b=pre[b];
    }if(a==b) b=a%n+1;
    bfs(b);
    for(int i=1;i<=n;++i)
        if(d[i]>x) return 0;
    return 1;
}
int main(){
    for(scanf("%d",&T);T--;){
        for(i=1;i<=n;++i) g[i].clear();
        for(scanf("%d",&n),i=1;i<n;++i)
            scanf("%d%d",&u,&v),g[u].push_back(v),g[v].push_back(u);
        for(l=0,r=n;l<r;){
            m=l+r>>1;
            if(ok(m)) r=m;
            else l=m+1;
        }if(ok(l)) printf("%d %d %d\n",l,a,b);
    }
}

Codeforces 486E LIS of Sequence

描述

The next “Data Structures and Algorithms” lesson will be about Longest Increasing Subsequence (LIS for short) of a sequence. For better understanding, Nam decided to learn it a few days before the lesson.

Nam created a sequence a consisting of n (1 ≤ n ≤ 105) elements a1, a2, …, an (1 ≤ ai ≤ 105). A subsequence ai1, ai2, …, aik where 1 ≤ i1 < i2 < … < ik ≤ n is called increasing if ai1 < ai2 < ai3 < … < aik. An increasing subsequence is called longest if it has maximum length among all increasing subsequences.

Nam realizes that a sequence may have several longest increasing subsequences. Hence, he divides all indexes i (1 ≤ i ≤ n), into three groups:

group of all i such that ai belongs to no longest increasing subsequences.
group of all i such that ai belongs to at least one but not every longest increasing subsequence.
group of all i such that ai belongs to every longest increasing subsequence. 

Since the number of longest increasing subsequences of a may be very large, categorizing process is very difficult. Your task is to help him finish this job.

Input

The first line contains the single integer n (1 ≤ n ≤ 105) denoting the number of elements of sequence a.

The second line contains n space-separated integers a1, a2, …, an (1 ≤ ai ≤ 105).

Output

Print a string consisting of n characters. i-th character should be ‘1’, ‘2’ or ‘3’ depending on which group among listed above index i belongs to.

人话

把给你的数分为3种类型。
1:不存在于任何最长上升子序列中。
2:存在于最长上升子序列中,但不是存在于全部的最长上升子序列中。
3:存在于所有最长上升子序列中。
输出所有数字的类型。

做法

正着算一遍最长上升子序列a,再倒着计算一遍最长下降子序列b
如果a[i]+b[i]-1

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define lb(a) lower_bound(d+1,d+n+1,a)
using namespace std;
typedef long long LL;
const int M=100010,inf=0x3f3f3f3f;
int x[M],d[M],a[M],b[M],ans[M],cnt[M];
int n,m,i,j,inc;
void f(){
    for(i=0;i<=n;++i) d[i]=inf;
    for(int i=1;i<=n;i++) {
        int ps=lb(x[i])-d;
        a[i]=ps;
        if(d[ps]==d[0]) inc++;
        d[ps]=x[i];
    }for(i=0;i<=n;++i) d[i]=inf;
    for(int i=n;i>0;i--) {
        int ps=lb(-x[i])-d;
        b[i]=ps;d[ps]=-x[i];
    }
}
int main(){
    for(scanf("%d",&n),i=1;i<=n;i++) scanf("%d",x+i);
    for(f(),i=1;i<=n;i++)
        if(a[i]+b[i]-1<inc) ans[i]=1;
        else cnt[a[i]]++;
    for(i=1;i<=n;i++)
        if(ans[i]) printf("1");
        else if(cnt[a[i]]==1) printf("3");
        else printf("2");
}

Codeforces 487E Tourists

描述

There are n cities in Cyberland, numbered from 1 to n, connected by m bidirectional roads. The j-th road connects city aj and bj.

For tourists, souvenirs are sold in every city of Cyberland. In particular, city i sell it at a price of wi.

Now there are q queries for you to handle. There are two types of queries:

"C a w": The price in city a is changed to w.
"A a b": Now a tourist will travel from city a to b. He will choose a route, he also doesn't want to visit a city twice. He will buy souvenirs at the city where the souvenirs are the cheapest (possibly exactly at city a or b). You should output the minimum possible price that he can buy the souvenirs during his travel.

More formally, we can define routes as follow:

A route is a sequence of cities [x1, x2, ..., xk], where k is a certain positive integer.
For any 1 ≤ i < j ≤ k, xi ≠ xj.
For any 1 ≤ i < k, there is a road connecting xi and xi + 1.
The minimum price of the route is min(wx1, wx2, ..., wxk).
The required answer is the minimum value of the minimum prices of all valid routes from a to b.

Input

The first line of input contains three integers n, m, q (1 ≤ n, m, q ≤ 105), separated by a single space.

Next n lines contain integers wi (1 ≤ wi ≤ 109).

Next m lines contain pairs of space-separated integers aj and bj (1 ≤ aj, bj ≤ n, aj ≠ bj).

It is guaranteed that there is at most one road connecting the same pair of cities. There is always at least one valid route between any two cities.

Next q lines each describe a query. The format is “C a w” or “A a b” (1 ≤ a, b ≤ n, 1 ≤ w ≤ 109).

Output

For each query of type “A”, output the corresponding answer.

Sample Input1

3 3 3
1
2
3
1 2
2 3
1 3
A 2 3
C 1 5
A 2 3

Sample Output1

1
2

Sample Input2

7 9 4
1
2
3
4
5
6
7
1 2
2 5
1 5
2 3
3 4
2 4
5 6
6 7
5 7
A 2 3
A 6 4
A 6 7
A 3 3

Sample Output2

2
1
5
3

人话

带修改的询问图上两点间最小权值

做法

考虑割点:对于每个连通块我们建一个节点存这个连通块中最小值,dfs序中不是最小的点向这个点连边。dfs序最小的点,让新点向它连边。修改时,把新点也更新。连通块与新点有两种关系:
1. 父亲:直接更新权值。
2. 儿子:两种情况:一是lca在新点的上方,肯定会经过修改点。否则lca就是这个新点,除了查询路径上的值,再查询这点和新点的fa就可以了。

代码如下

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
#define pb(a,b) g[a].push_back(b)
using namespace std;
const int M=200010,inf=1e9+9;
multiset<int> s[M];
vector<int> g[M];
int n,m,q,i,j;
int w[M],T[M<<2];
int tot,he[M],ne[M<<1],to[M<<1];
int tp,tm,cnt,low[M],dfn[M],st[M],bl[M];
int ps,dep[M],fa[M],sz[M],son[M],top[M],id[M];
void add(int x,int y){
     to[++tot]=y;ne[tot]=he[x];he[x]=tot;
}
void tarjan(int x,int f){
    dfn[x]=low[x]=++tm;st[++tp]=x;
    for(int y,i=0;i<g[x].size();++i)
        if(!dfn[y=g[x][i]]) {
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x]){
                for(++cnt;1;) {
                    int t=st[tp--];bl[t]=cnt;
                    s[cnt].insert(w[t]);add(cnt,t);
                    if(t==y) break;
                }add(x,cnt);
            }
        }else if (y!=f) low[x]=min(low[x],dfn[y]);
}
void mdf(int x,int l,int r,int o,int v){
    if(l==r){T[x]=v;return;}
    int mid=l+r>>1;
    if(o<=mid) mdf(x<<1,l,mid,o,v);
    else mdf(x<<1|1,mid+1,r,o,v);
    T[x]=min(T[x<<1],T[x<<1|1]);
}

void mdf(int x,int v){
    if (bl[x]){
        int t=bl[x];
        s[t].erase(s[t].find(w[x]));
        s[t].insert(v);
        mdf(1,1,ps,id[t],*s[t].begin());
    }w[x]=v;mdf(1,1,ps,id[x],v);
}
int qu(int x,int l,int r,int L,int R){
    if(l==L&&r==R) return T[x];
    int mid=l+r>>1;
    if(R<=mid) return qu(x<<1,l,mid,L,R);
    else if(L>mid) return qu(x<<1|1,mid+1,r,L,R);
    else return min(qu(x<<1,l,mid,L,mid),qu(x<<1|1,mid+1,r,mid+1,R));
}
int qu(int x,int y){
    int ans=inf;
    for(;top[x]!=top[y];){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=min(ans,qu(1,1,ps,id[top[x]],id[x]));
        x=fa[top[x]];
    }if(dep[x]<dep[y]) swap(x,y);
    ans=min(ans,qu(1,1,ps,id[y],id[x]));
    if(y>n&&fa[y]) ans=min(ans,w[fa[y]]);
    return ans;
}
void dfs(int x){
    sz[x]=1;
    for(int y,i=he[x];i;i=ne[i])
        if((y=to[i])!=fa[x]){
            fa[y]=x,dep[y]=dep[x]+1;
            dfs(y);sz[x]+=sz[y];
            if (sz[y]>sz[son[x]]) son[x]=y;
        }
}
void dfs2(int x,int chain){
    id[x]=++ps,top[x]=chain;
    if(son[x]) dfs2(son[x],chain);
    for(int y,i=he[x];i;i=ne[i])
        if ((y=to[i])!=son[x]&&y!=fa[x]) dfs2(y,y);
}
int main(){
    for(scanf("%d%d%d",&n,&m,&q),i=1;i<=n;++i) scanf("%d",w+i);
    for(int x,y,i=1;i<=m;i++) scanf("%d%d",&x,&y),pb(x,y),pb(y,x);
    for(cnt=n,tarjan(1,0),dfs(1),dfs2(1,1),i=1;i<=ps;++i)
        if(i<=n) mdf(1,1,ps,id[i],w[i]);
        else mdf(1,1,ps,id[i],*s[i].begin());
    for(int x,y;q--;){
        char ch;scanf("\n%c%d%d",&ch,&x,&y);
        if(ch=='C') mdf(x,y);
        else printf("%d\n",qu(x,y));
    }return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值