BNU Training 2015.08.17

        题目链接

        这套题目比较简单,为了庆祝为数不多的AK,决定把题解发一下。233....

        A. Smooth Visualization(UVALive 5870 Smooth Visualization)

        签到题一个,搞搞搞就行了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 10000;

char ans[10][maxn];
char ch[maxn];

void solve()
{
    int len = strlen(ch);
    int cnt = ch[0] - '0';
    cnt = 7 - cnt;
    int q = ch[0] - '0';
    for(int i = 0; i < 7; i ++)
    {
        if(cnt)
        {
            ans[i][0] = '*'; cnt --;
        }
        else ans[i][0] = '+';
    }
    int n = 1;
    for(int i = 1; i < len; i ++)
    {
        q = max(q, ch[i] - '0');
        int tmp = ch[i] - ch[i - 1];
        if(abs(tmp) <= 1)
        {
            cnt = 7 - (ch[i] - '0');
            for(int j = 0; j < 7; j ++)
            {
                if(cnt)
                {
                    ans[j][n] = '*'; cnt --;
                }
                else ans[j][n] = '+';
            }
            n ++;
        }
        else if(tmp > 0)
        {
            ch[i - 1] ++;
            cnt = 7 - (ch[i - 1] - '0');
            for(int j = 0; j < 7; j ++)
            {
                if(cnt)
                {
                    ans[j][n] = '*'; cnt --;
                }
                else ans[j][n] = '+';
            }
            n ++; i --;
        }
        else
        {
            ch[i - 1] --;
            cnt = 7 - (ch[i - 1] - '0');
            for(int j = 0; j < 7; j ++)
            {
                if(cnt)
                {
                    ans[j][n] = '*'; cnt --;
                }
                else ans[j][n] = '+';
            }
            n ++;  i --;
        }
    }
    for(int i = 0; i < 7; i ++)
        ans[i][n] = 0;
    for(int i = 7 - q; i < 7; i ++)
        puts(ans[i]);
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%s", ch);
        solve();
    }
    return 0;
}
         B. Arnooks's Defensive Line(UVALive 5871 Arnooks's Defensive Line )

         因为看起来是单组数据,n=500000,cdq分治的话,算了下时间复杂度正好。于是就是一道cdq分治裸题。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 500100;

struct Node
{
    char op;
    int l, r, id;
    void in(int i)
    {
        char ch[2];
        scanf("%s%d%d", ch, &l, &r);
        op = ch[0]; id = i;
    }
    bool operator < (const Node& rhs) const
    {
        return l < rhs.l;
    }
}a[maxn];

int C[maxn];

void add(int x, int ad)
{
    while(x < maxn)
    {
        C[x] += ad;
        x += x & (-x);
    }
}

int sum(int x)
{
    int ret = 0;
    while(x)
    {
        ret += C[x];
        x -= x & (-x);
    }
    return ret;
}

int n;
vector vec;
int ans[maxn];

void divide(int l, int r)
{
    if(l == r) return ;
    int m = (l + r) >> 1;
    divide(l, m);
    divide(m + 1, r);
    sort(a + l, a + m + 1);
    sort(a + m + 1, a + r + 1);
    int cnt = 0;
    for(int i = m + 1, j = l; i <= r; i ++)
    {
        while(j <= m && a[j].l <= a[i].l)
        {
            if(a[j].op != '?') add(a[j].r, 1), cnt ++;
            j ++;
        }
        if(a[i].op == '?')
        {
            if(ans[a[i].id] == -1) ans[a[i].id] = 0;
            ans[a[i].id] += cnt - sum(a[i].r - 1);
        }
    }
    for(int i = m + 1, j = l; i <= r; i ++)
    {
        while(j <= m && a[j].l <= a[i].l)
        {
            if(a[j].op != '?') add(a[j].r, -1);
            j ++;
        }
    }
}

void solve()
{
    vec.clear();
    for(int i = 1; i <= n; i ++)
    {
        vec.push_back(a[i].r);
    }
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    for(int i = 1; i <= n; i ++)
    {
        a[i].r = lower_bound(vec.begin(), vec.end(), a[i].r) - vec.begin() + 1;
    }
    CLR(C, 0);
    CLR(ans, -1);
    divide(1, n);
    for(int i = 1; i <= n; i ++)
        if(ans[i] != -1) printf("%d\n", ans[i]);
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
        a[i].in(i);
    solve();
    return 0;
}
        C. Equivalence(UVALive 5872 Equivalence )
        这题随便模拟就好了。做的时候uvalive崩掉了,于是连交了十来发。。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 1200000000000000000ll
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;

map mp;
map ::iterator it;

struct Exp{
    vector _exp;
    vector xishu;
    char tmp[100];
    void init(){
        _exp.clear();
        xishu.clear();
    }
    void hebing(){
        mp.clear();
        for(int i=0;i<_exp.size();i++){
            sort(_exp[i].begin(),_exp[i].end());
            mp[_exp[i]]+=xishu[i];
        }
        init();
        for(it=mp.begin();it!=mp.end();++it){
            if(it->yy!=0) _exp.push_back(it->xx),xishu.push_back(it->yy);
        }
    }
};

Exp add(Exp a,Exp b){
    Exp ans;ans=b;
    for(int i=0;i= '0' && a[l] <= '9')
        {
            ret._exp.push_back("1");
            ret.xishu.push_back(a[l] - '0');
        }
        else
        {
            string str = "";
            str += a[l];
            ret._exp.push_back(str);
            ret.xishu.push_back(1);
        }
        return ret;
    }
    vector vec;
    string str = "";
    for(int i = l; i <= r; i ++)
    {
        Exp tmp;
        if(a[i] == '(')
        {
            int j = i + 1, cnt = 1;
            while(j <= r)
            {
                if(a[j] == '(') cnt ++;
                else if(a[j] == ')') cnt --;
                if(cnt == 0) break;
                j ++;
            }
            tmp = dfs(i + 1, j - 1);
            i = j;
        }
        else
        {
            tmp = dfs(i, i);
        }
        i ++;
        if(i <= r) str += a[i];
        vec.push_back(tmp);
    }
    Exp tmp; tmp.init();
    for(int i = 0; i < vec.size(); i ++)
    {
        tmp = vec[i];
        int j = i;
        while(i < str.size() && str[i] == '*')
        {
            tmp = mult(tmp, vec[i + 1]);
            i ++;
        }
        if(j)
        {
            if(str[j - 1] == '+') ret = add(ret, tmp);
            else
            {
                ret = sub(ret, tmp);
            }
        }
        else ret = tmp;
    }
    return ret;
}

char ch1[10010], ch2[10010];
void solve()
{
    gets(ch1);
    gets(ch2);
    int len = strlen(ch1);
    a = "(";
    for(int i = 0; i < len; i ++)
    {
        if(ch1[i] == ' ' || ch1[i] == '\t') continue;
        a += ch1[i];
    }
    a += ")";
    b = "";
    int len2 = strlen(ch2);
    for(int i = 0; i < len2; i ++)
    {
        if(ch2[i] == ' ' || ch2[i] == '\t') continue;
        b += ch2[i];
    }
    a += "-(";
    a += b;
    a += ")";
    for(int i = 0; i < a.size(); i ++)
    {
        if(a[i] >= 'A' && a[i] <= 'Z')
        {
            a[i] = a[i] - 'A' + 'a';
        }
    }
    Exp ret = dfs(0, a.size() - 1);
    if(ret._exp.size() == 0) puts("YES");
    else puts("NO");
}

int main(){
    int T;
    scanf("%d", &T);
    getchar();
    while(T --)
    {
        solve();
    }
    return 0;
}

        D. Tree Inspections (UVALive 5873 Tree Inspections )

        这题题意是给你n个点,然后m个横线或者竖线,如果满足在直线上站着,能垂直看到60%以上的点的话,就输出PASSED。

        横线和竖线情况相同,对于一个横线,只需要考虑他和相邻横线之间的看见的情况就可以了。可以分向上看和向下看两种情况。然后模拟一下就行了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;

const int maxn = 100100;

struct Point
{
    int x, y, id;
    void inpt(int i)
    {
        scanf("%d%d", &x, &y);
        id = i;
    }
}p[maxn];

bool cmp1(Point a, Point b)
{
    return a.x < b.x;
}

bool cmp2(Point a, Point b)
{
    return a.y < b.y;
}

vector H, V;

bool vis[maxn];

void solve()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i ++)
        p[i].inpt(i);
    H.clear(); V.clear();
    for(int i = 0; i < m; i ++)
    {
        char op[2]; int x;
        scanf("%s%d", op, &x);
        if(op[0] == 'H') H.push_back(x);
        else V.push_back(x);
    }
    CLR(vis, false);
    sort(H.begin(), H.end());
    sort(V.begin(), V.end());
    sort(p, p + n, cmp1);
    map mp;
    for(int i = 0, j = 0; i < H.size(); i ++)
    {
        int h = H[i];
        mp.clear();
        while(j < n && p[j].x <= h)
        {
            if(mp.count(p[j].y))
            {
                if(p[mp[p[j].y]].x > p[j].x)
                {
                    mp[p[j].y] = j;
                }
            }
            else mp[p[j].y] = j;
            j ++;
        }
        map::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }

    for(int i = 0, j = n - 1; i < H.size(); i ++)
    {
        int h = H[i];
        mp.clear();
        while(j >= 0 && p[j].x >= h)
        {
            if(mp.count(p[j].y))
            {
                if(p[mp[p[j].y]].x < p[j].x)
                {
                    mp[p[j].y] = j;
                }
            }
            else mp[p[j].y] = j;
            j --;
        }
        map::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }

    sort(p, p + n, cmp2);

    for(int i = 0, j = 0; i < V.size(); i ++)
    {
        int v = V[i];
        mp.clear();
        while(j < n && p[j].y <= v)
        {
            if(mp.count(p[j].x))
            {
                if(p[mp[p[j].y]].y > p[j].y)
                {
                    mp[p[j].x] = j;
                }
            }
            else mp[p[j].x] = j;
            j ++;
        }
        map::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }

    for(int i = 0, j = n - 1; i < V.size(); i ++)
    {
        int v = V[i];
        mp.clear();
        while(j >= 0 && p[j].y >= v)
        {
            if(mp.count(p[j].x))
            {
                if(p[mp[p[j].y]].y < p[j].y)
                {
                    mp[p[j].x] = j;
                }
            }
            else mp[p[j].x] = j;
            j --;
        }
        map::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }
    int ans = 0;
    for(int i = 0; i < n; i ++)
        if(vis[i]) ans ++;//, printf("%d -- %d\n", p[i].x, p[i].y);
    if(ans * 10 >= n * 6) puts("PASSED");
    else puts("FAILED");
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        solve();
    }
    return 0;
}

       E. Social Holidaying(UVALive 5874 Social Holidaying)

       这题直接最大匹配就过了。可以的就连双向边,然后最大匹配除以二

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn=1000;

int a[maxn],b[maxn];

struct BPM
{
  int n, m;               // 左右顶点个数
  vector G[maxn];      // 邻接表
  int left[maxn];         // left[i]为右边第i个点的匹配点编号,-1表示不存在
  bool T[maxn];           // T[i]为右边第i个点是否已标记

  void init(int n, int m) {
    this->n = n;
    this->m = m;
    for(int i=0;i<=n;i++) G[i].clear();
  }

  bool match(int u){
    for(int i = 0;i < G[u].size(); i++) {
        int v=G[u][i];
        if(!T[v]) {
          T[v] = true;
          if (left[v] == -1 || match(left[v])){
            left[v] = u;
            return true;
          }
        }
    }
    return false;
  }
  // 求最大匹配
  int solve() {
    memset(left, -1, sizeof(left));
    int ans = 0;
    for(int u = 0; u < n; u++) {
      memset(T, 0, sizeof(T));
      if(match(u)) ans++;
    }
    return ans;
  }
}sol;

set _hash;

int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n,m;scanf("%d%d",&n,&m);
        _hash.clear();
        for(int i=0;i

       F. Orienteering(UVALive 5875 Orienteering)
       这题发现不能背包距离,但是可以背包分数呀!于是愉快的背包出所有分数的最短距离。然后每个询问查一下就行了。查的时候随便查,二分什么的都行。暴力也能过。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 60600;
#define MOD 1000000009

double eps = 1e-8;

double dp[33][maxn];

double sqr(double x){
    return x*x;
}

int sign(double x){
    return (x>eps)-(x<-eps);
}

struct Point
{
    double x, y;
    int s;
    void inpt()
    {
        scanf("%lf%lf%d", &x, &y, &s);
    }
}p[40];

double dist(Point a,Point b){
    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}

int Max[40];

double dis[40][40];
double ans[maxn];
int n;

void solve()
{
    for(int i = 1; i <= n; i ++)
        p[i].inpt();
    p[0].x = 0; p[0].y = 0; p[0].s = 0;
    for(int i = 0; i <= n; i ++)
    {
        for(int j = 0; j <= n; j ++)
            dis[i][j] = dist(p[i], p[j]);
    }
    for(int i = 0; i <= n; i ++)
    {
        for(int j = 0; j < maxn; j ++)
            dp[i][j] = 1e30;
    }
    dp[0][0] = 0;
    Max[0] = 0;
    for(int i = 1; i <= n; i ++)
    {
        Max[i] = 0;
        for(int j = 0; j < i; j ++)
        {
            for(int k = 0; k <= Max[j]; k ++)
            {
                dp[i][k + p[i].s] = min(dp[i][k + p[i].s], dp[j][k] + dis[i][j] - dis[j][0] + dis[i][0]);
            }
            Max[i] = max(Max[i], Max[j] + p[i].s);
        }
    }
    for(int i = 0; i < maxn; i ++)
        ans[i] = 1e20;
    int tot = 0;
    for(int i = 0; i <= n; i ++)
    {
        tot = max(tot, Max[i]);
        for(int j = 0; j <= Max[i]; j ++)
        {
            ans[j] = min(ans[j], dp[i][j]);
        }
    }
    char ch[100]; double d;
    while(scanf("%s%lf", ch, &d), ch[0] != '#')
    {
        int out = -1;
        for(int i = 0; i <= tot; i ++)
        {
            if(sign(d - ans[i]) >= 0)
            {
                out = i;
            }
        }
        printf("%s: %d\n", ch, out);
    }
}

int main()
{
    int T, cas = 1;
    while(scanf("%d", &n), n)
    {
        printf("Race %d\n", cas ++);
        solve();
    }
}
        G. Writings on the Wall(UVALive 5876 Writings on the Wall)

        求两个串可重叠的相连有多少种情况,扩展kmp裸题。。当s后缀和t公共前缀等于s后缀长度的时候,就是可以拼接的时候。然后。。ans++

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 1200000000000000000ll
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 100100;
#define MOD 1000000007

const int N = 101010;
int next[N],extand[N];
void getnext(char *T) // next[i]: 以第i位置开始的子串 与 T的公共前缀
{
    int i,length = strlen(T);
    next[0] = length;
    for(i = 0; i= p )
        {
            int j = (p-k+1)>0? (p-k+1) : 0;
            while(k+jTlen?Tlen:Slen;
    while(a= p )
        {
            int j = (p-k+1)>0? (p-k+1) : 0;
            while(k+j

       H. Robotic Traceur(UVALive 5877 Robotic Traceur)
       就是最小步数的最短路,并没有发现什么坑。。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;

const double eps=1e-8;

double sqr(double x)
{
    return x*x;
}

int sign(double x)
{
    return (x>eps)-(x<-eps);
}

const int maxn = 1010;

struct Point
{
    double x,y;
    Point(double _x=0,double  _y=0)
    {
        x=_x,y=_y;
    }
    void input()
    {
        scanf("%lf%lf",&x,&y);
    }
} p[1024];

double dist(Point a,Point b){
    return sqr(a.x-b.x)+sqr(a.y-b.y);
}

vector G[maxn];
bool vis[maxn];
int dp[maxn];

int gao(int s, int t)
{
    queue Q;
    Q.push(s);
    CLR(vis, false);
    CLR(dp, INF);
    dp[s] = 0;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        vis[u] = false;
        for(int i = 0; i < G[u].size(); i ++)
        {
            int v = G[u][i];
            if(dp[v] > dp[u] + 1)
            {
                dp[v] = dp[u] + 1;
                if(!vis[v]) Q.push(v);
                vis[v] = true;
            }
        }
    }
    return dp[t];
}

void solve()
{
    int n, s, t;
    double l1, l2;
    scanf("%d%d%d%lf%lf", &n, &s, &t, &l1, &l2);
    l1 += l2;
    for(int i = 1; i <= n; i ++)
        p[i].input(), G[i].clear();
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= n; j ++) if(i != j)
        {
            if(sign(dist(p[i], p[j]) - sqr(l1)) <= 0)
            {
                G[i].push_back(j);
            }
        }
    }
    int ret = gao(s, t);
    if(ret == INF) puts("Impossible");
    else printf("%d\n", ret);
}
        I. Shortest Leash(UVALive 5878 Shortest Leash)

        其实我发这篇文的目的,就是说一下这道题。。

        这道题上来就被秒了,然而我感觉这道题很神啊!赛后发现大家都是用黑科技过的。。怪不得过了那么多。。个人感觉我们的思路是“杠杠的”正确。

        最后的答案,肯定是2^n种情况求出的点后排的凸包上的点。然后,假如我们已经用了前i个向量,而且求出了相应的凸包,那么,考虑第i+1个向量对当前的凸包的影响,就是把当前凸包向着i+1这个向量的两个方向拉伸了一些长度,稍微想象一下可以知道,这样的拉伸最多增加两个点啊!!于是,每次增加向量最多增加两个点。。于是,按顺序添加向量,维护凸包就可以了。。。

        加向量,排凸包,加向量,排凸包。。复杂度O(n^2*log(n))。

#include
#include
#include
#include
using namespace std;
const double inf=1e10;
const double eps=1e-8;

double sqr(double x){
    return x*x;
}

int sign(double x){
    return (x>eps)-(x<-eps);
}

struct Point{
    double x,y;
    Point(double _x=0,double  _y=0){
        x=_x,y=_y;
    }
    Point operator+(const Point &a){
        return Point(x+a.x,y+a.y);
    }
    Point operator-(const Point &a){
        return Point(x-a.x,y-a.y);
    }
    void input(){
        scanf("%lf%lf",&x,&y);
    }
}p[1024],v[1024],res[1024];

double mult(Point sp,Point ep,Point op){
    return (sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y);
}
bool operator<(const Point &l,const Point &r){
    return l.y=0) top--;
        res[++top]=pnt[i];
    }
    len=top;res[++top]=pnt[n-2];
    for(i=n-3;i>=0;i--){
        while(top!=len&&mult(pnt[i],res[top],res[top-1])>=0) top--;
        res[++top]=pnt[i];
    }
    return top;
}

double dist(Point a,Point b){
    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}

int main(){
    int n;
    while(scanf("%d",&n),n){
        p[0]=Point(0,0);
        int m=1;
        double ans=-inf;
        for(int i=0;i





你可能感兴趣的:(比赛总结)