2014 Super Training #6 F Search in the Wiki --集合取交+暴力

原题: ZOJ 3674 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3674

题意不难理解,很容易想到用暴力,但是无从下手,不知道怎么实现。后来看了网上的代码,直接用vector和map暴力,用到了set_intersection()函数,之前也听过这个函数,但是一直没写过,于是照着他的代码打了一遍,算是见识一下这个函数了。

代码看一下就能看懂了,关键看自己能不能写出来。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <cstdlib>
using namespace std;
#define N 10007

char name[35],ss[210],tips[210];
int check[110];

int main()
{
    int n,m,i,j,a,b;
    int cword,ctips,ind,ccheck;
    while(scanf("%d",&n)!=EOF)
    {
        cword = ctips = 0;
        map<string,int> word;
        map<string,int> tip;
        map<int,string> atip;
        vector<int> G[110],K1,K2;
        for(j=1;j<=n;j++)
        {
            scanf("%s",name);
            if(!word[name])
                word[name] = ++cword;  //hash
            a = word[name];
            getchar();
            gets(ss);
            ind = 0;
            for(i=0;ss[i];i++)
            {
                if(ss[i] == ‘ ‘)
                {
                    tips[ind] = ‘\0‘;
                    if(!tip[tips])
                    {
                        tip[tips] = ++ctips;
                        atip[ctips] = tips;
                    }
                    b = tip[tips];
                    G[a].push_back(b);
                    ind = 0;
                }
                else
                    tips[ind++] = ss[i];
            }
            tips[ind] = 0;
            if(!tip[tips])
            {
                tip[tips] = ++ctips;
                atip[ctips] = tips;
            }
            b = tip[tips];
            G[a].push_back(b);
            sort(G[a].begin(),G[a].end());
        }
        scanf("%d",&m);
        getchar();
        while(m--)
        {
            ccheck = 0;
            gets(ss);
            ind = 0;
            for(i=0;ss[i];i++)
            {
                if(ss[i] == ‘ ‘)
                {
                    name[ind] = 0;
                    check[ccheck++] = word[name];
                    ind = 0;
                }
                else
                    name[ind++] = ss[i];
            }
            name[ind] = 0;
            check[ccheck++] = word[name];
            K1.clear();
            vector<int> ::iterator it;
            for(it=G[check[0]].begin();it<G[check[0]].end();it++)
                K1.push_back(*it);
            for(i=1;i<ccheck;i++)
            {
                K2.clear();
                set_intersection(K1.begin(),K1.end(),G[check[i]].begin(),G[check[i]].end(),back_inserter(K2));
                i++;
                if(i >= ccheck)  //last one
                {
                    K1.clear();
                    for(it=K2.begin();it<K2.end();it++)
                        K1.push_back(*it);
                    break;
                }
                K1.clear();
                set_intersection(K2.begin(),K2.end(),G[check[i]].begin(),G[check[i]].end(),back_inserter(K1));
            }
            //最终结果看K1
            if(!K1.size())
            {
                puts("NO");
                continue;
            }
            set<string> ans;
            for(it=K1.begin();it<K1.end();it++)
                ans.insert(atip[*it]);
            set<string>::iterator st;
            st = ans.begin();
            cout<<*st;
            for(st++;st!=ans.end();st++)
                cout<<" "<<*st;
            puts("");
        }
    }
    return 0;
}

2014 Super Training #6 F Search in the Wiki --集合取交+暴力,布布扣,bubuko.com

时间: 2024-12-15 20:44:14

2014 Super Training #6 F Search in the Wiki --集合取交+暴力的相关文章

2014 Super Training #1 F Passage 概率DP

原题: HDU 3366   http://acm.hdu.edu.cn/showproblem.php?pid=3366 本来用贪心去做,怎么都WA,后来看网上原来是一个DP题. 首先按P/Q来做排序,即P越大,Q越小就越好,这样可以确保先选最优的路走. dp[i][j]表示已经到了第i条路(说明前i-1条都没成功的情况),还剩j块钱时能够走出去的概率. 则方程: dp[i][j] = way[i].P + way[i].Q*(dp[i+1][j-1]) + way[i].D*(dp[i+1]

2014 Super Training #9 F A Simple Tree Problem --DFS+线段树

原题: ZOJ 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686 这题本来是一个比较水的线段树,结果一个mark坑了我好几个小时..哎.太弱. 先DFS这棵树,树形结构转换为线性结构,每个节点有一个第一次遍历的时间和最后一次遍历的时间,之间的时间戳都为子树的时间戳,用线段树更新这段区间即可实现更新子树的效果,用到懒操作节省时间. 坑我的地方: update时,不能写成:tree[rt].mark = 1,

2014 Super Training #2 F The Bridges of Kolsberg --DP

原题:UVA 1172  http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3613 动态规划问题. 定义: dp[i] = 右岸前i个村庄(m岸)能够与左岸(n岸)不交叉匹配的最大权值和最小桥数 (用pair<int,int> 维护两个值) 方程: dp[i].first = max(dp[i].first,dp[i-1].fir

2014 Super Training #7 F Power of Fibonacci --数学+逆元+快速幂

原题:ZOJ 3774  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3774 ---------------------------------------------------------------------------------------------------------------------- 这题比较复杂,看这篇比较详细:http://blog.csdn.net/acdreamers/artic

2014 Super Training #1 B Fix 状压DP

原题: HDU 3362 http://acm.hdu.edu.cn/showproblem.php?pid=3362 开始准备贪心搞,结果发现太难了,一直都没做出来.后来才知道要用状压DP. 题意:题目给出n(n <= 18)个点的二维坐标,并说明某些点是被固定了的,其余则没固定,要求添加一些边,使得还没被固定的点变成固定的,可见题目中的图形sample. 由于n很小,而且固定点的顺序没有限制,所以需要用状态压缩DP. 注意:1.当一个没固定的点和两个固定了的点连接后,该点就被(间接)固定了(

2014 Super Training #7 E Calculate the Function --矩阵+线段树

原题:ZOJ 3772 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3772 这题算是长见识了,还从没坐过矩阵+线段树的题目呢,不要以为矩阵就一定配合快速幂来解递推式的哦. 由F(x)=F(x-1)+F(x-2)*A[x],转化为矩阵乘法:  ===> 所以维护一颗线段树,线段树的每个结点保存一个矩阵,叶子节点为: a[0][0] = a[1][0] = 1, a[0][1] = Ax, a[1][1] = 0的形式

2014 Super Training #2 C Robotruck --单调队列优化DP

原题: UVA 1169  http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3610 大白书上的原题. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algor

2014 Super Training #8 B Consecutive Blocks --排序+贪心

当时不知道怎么下手,后来一看原来就是排个序然后乱搞就行了. 解法不想写了,可见:http://blog.csdn.net/u013368721/article/details/28071241 其实就是滑动窗口的思想. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algor

2014 Super Training #1 C Ice-sugar Gourd 模拟,扫描线

原题 HDU 3363 http://acm.hdu.edu.cn/showproblem.php?pid=3363 给你一个串,串中有H跟T两种字符,然后切任意刀,使得能把H跟T各自分为原来的一半. 解法: 把串想象成一个环,只要满足H跟T都为偶数个,那么就可以做一条过圆心的直线把H跟T平分掉,过直线,只要考虑平分H或者T中的一个就可以了,因为直线本来就把环平分,而此时平分了H或者T,那么剩下的那个也是平分掉的. 具体证明: http://hi.baidu.com/superlong/item