• 这个随笔用用来放一些好的思想和思考方式(暂时secret)


    一:

    给你一个只有4和7的数字,求这是第几个幸运数字?

    思路:

    我们把4映射成0,7映射成1,然后就如下枚举:0,1,00,01,10,11。因为是映射的,所以可以前导0,然后我们就会知道给出的那个数字在里面的规律了,找出来就好了。

    关键:映射思想

    二:CF 319 DIV1 A

    一种组合计数问题:

    给你一个01串(因为是字符串,可以前导0),长度为n。然后给你一个编号为0到(2^n)-1的所有数字,将这些所有编号取异或然后让原数字和这个异或的数字配对成(a,b)。问,有多少套这样的数,满足(a,b),(c,d),其中c>a,b>d。

    思路:

    a和c的右边是一定是一样的,那么二进制中,c到某一位的数字是0,而a是1,那么无论后面的数字再怎么枚举都不可能a>=c,所以我们只需要固定这一位,然后左边的高位一样,右边的可以不一样(不一样的相乘即可),这样就OK了。

    关键:移位、固定条件、等思想(这个思想在CD667 div2的D也有)

    三:CF 315 DIV2 C

    题目大意:

    有n个人,分别这些人有a[i]的rank,然后通过一定的计算公式,计算出他们的值,如果其中的值小于k,那么就删除这个数字。注意,这个数组是动态的,例如,原来有5个,那么删除了第二个以后后面的3,4,5的a[i]的位置就变成了2,3,4了。

    思路:

    因为第一个是0,那么我们只需要知道下面所计算的,如果遇到一个tmp<k的就直接删除就可以了,并不需要每一次都重新计算所有的值

    关键:无论怎么样的规律,都要先试试看直接按照顺序做或者逆序做

    四:UVA1103 world final2011

    题目大意,给你几个图片,每个图片都有特征,再给你为h*w的数组,输出数组中描述的图片。(按照字母大小排序)

    思路:

    dfs,每个特征就是其中的空白块有几个。

    这里的一些思想

    ①把所有不同类型的块弄成不同的颜色,再统计即可

    ②利用vector<set<int>>来统计集合

    关键:让特征不同的对应不同的值,使得容易区分

    五:八皇后问题书p193

    八皇后问题就是一个简单的回溯法,但是从中我们要获得一些思想:

    ①主对角线和副对角线之间是有关联的,y-x表示的是主对角线的特征,y+x表示的是副对角线的特征(如果有两个这样的是相等的话,那就表示他们是在同一条对角线上)。或者用vis[1][cur+i] and vis[2][cur-i+n]来表示主和副对角线

    六:理想路径 UVA1599 NERRC 2010

    题目大意:给n个点,m条边(2<=n<=100000, 1<=m<=200000)的无向图,每条边有一个颜色。求从1到n的路径,使得经过的边最少,如果有多条路径,那么就是找经过的color字典序最小,且输出路径上的color(颜色为1-1e9)

    思路一:

    反向bfs找路径d,再正向bfs每次找目前节点上color最小的那条边即可。

    #include<bits/stdc++.h>
    
    using namespace std;
    const int maxn = 200000 + 5;
    const int inf = 0x3f3f3f3f;
    struct edge{
        int u, v;
        int color;
        edge(int uu, int vv, int cc): u(uu), v(vv), color(cc){}
    };
    vector<edge> G[maxn];
    int d[maxn];
    int n, m;
    
    
    void init(){
        for (int i = 0; i < n; i++) d[i] = inf;
        for (int i = 0; i < n; i++) G[i].erase(G[i].begin(), G[i].end());
        for (int i = 0; i < m; i++){
            int u, v, c;
            scanf("%d%d%d", &u, &v, &c);
            if (u == v) continue;
            G[u - 1].push_back(edge(u - 1, v - 1, c));
            G[v - 1].push_back(edge(v - 1, u - 1, c));
        }
    }
    
    
    void bfs1(int s){
        queue<int> que;
        que.push(s);
        d[s] = 0;
        while (!que.empty()){
            int u = que.front();
            que.pop();
            for (int i = 0; i < G[u].size(); i++){
                edge e = G[u][i];
                if (d[u] < inf && d[u] + 1 < d[e.v]){
                    d[e.v] = d[u] + 1;
                    que.push(e.v);
                }
            }
        }
    }
    
    vector <int> ans;
    
    void bfs2(int s){
        ans.erase(ans.begin(), ans.end());
        queue<int> que;
        que.push(s);
        //printf("%d
    ", d[s]);
        int cnt = d[s] - 1;
        vector <int> v;
        int c = inf;
        while (!que.empty()){
            int u = que.front();
            que.pop();
            for (int i = 0; i < G[u].size(); i++){
                edge e = G[u][i];
                if (cnt != d[e.v]) continue;
                //printf("cnt = %d
    ", cnt);
                if (c > e.color){
                    v.erase(v.begin(), v.end());
                    v.push_back(e.v);
                    c = e.color;
                }
                else if (c == e.color){
                    v.push_back(e.v);
                }
            }
            if (c == inf)
            if (que.empty() && v.size()){
                for (int i = 0; i < v.size(); i++){
                    que.push(v[i]);
                }
                ans.push_back(c);
                c = inf;
                cnt--;
                v.erase(v.begin(), v.end());
            }
        }
        int len = ans.size();
        printf("len = %d
    ", len);
        for (int i = 0; i < len; i++){
            printf("%d%c", ans[i], i == len - 1 ? '
    ' : ' ');
        }
    }
    
    int main(){
        while (scanf("%d%d", &n, &m) == 2){
            init();
            bfs1(n - 1);
            bfs2(0);
        }
        return 0;
    }
    View Code

    关键:两次bfs的作用不同。 倒叙。 

    思路二:

    一次bfs就够了(我不会。。。)

    七:修改天平UVA12166 NWERC2008

    题目大意:给一个深度不超过16的二叉树,代表一个天平,每个杆都挂在中间,每个秤砣的重量已知。问,至少修改多少个秤砣的重量才能让天平平衡?

    吐槽:

    T了我一脸。。。而且自己的之前思路还错了。。。

    思路:

    由于是天平,且是二叉树,因此,我们知道,修改一个点就等于要修改全部的点。因此,我们可以固定一下。首先我们选取二叉树上的一点为值,如果天平要平衡,那么天平上的总重量必然为(目前选取的这个重量为w,深度为d)w<<d。然后我们把每个值所对应的w<<d求出来,用map保存,然后最后扫一遍map就行了。

    关键:定点,平衡与总和,逆向(就是反过来用w<<d求)

    这里知道了strlen(char数组)是O(n)的方法寻找的,所以在多组的时候一定要小心。(因为这个T了一脸)

    还有就是map的遍历map<>::iterator it = map.begin()  for(; it != map.end(); it++){}

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long LL;
    const int inf = 0x3f3f3f3f;
    const int maxn = 5000000 + 5;
    //char ch[maxn];
    map <LL, int> m;
    string ch;
    
    int main(){
        int t; cin >> t;
        while (t--){
            //scanf("%s", ch);
            cin >> ch;
            m.clear();
            int sum = 0;
            int nowd = 0;
            for (int i = 0; i < ch.size()/*strlen(ch)*/; i++){
                if (ch[i] == ',') continue;
                else if (ch[i] == '[') nowd++;
                else if (ch[i] == ']') nowd--;
                else {
                    LL val = ch[i] - '0';
                    while (ch[i + 1] >= '0' && ch[i + 1] <= '9'){
                        val = LL(val * 10 + ch[i + 1] - '0');
                        i += 1;
                    }
                    val <<= nowd;
                    m[val] += 1;
                    sum++;
                }
            }
            int ans = inf;
            map<LL, int>::iterator it = m.begin();
            for ( ; it != m.end(); it++){
                ans = min(ans, sum - it->second);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code

    八:寻找矩形(一次多校赛前的测试,估计题目已经无法交了:链接

    账号密码team244 123570

    题目大意:给你n个点,n<1e5,每个点都有坐标(x,y)(xandy的绝对值都小于1e9),有一个矩形,每条边都平行于x和y。问有多少个矩形符合每条边上都有m个点。(每个顶点都必须有一个点)

    思路:

    离散化以后枚举点,然后之前将所有点按x排序,y排序,最后再寻找这个点上方的m-1个和左边的m-1个,然后找到以后得到新的x和y,然后判断这个x和y存不存在即可。

    关键:离散化,上方枚举和下方枚举

    #include<bits/stdc++.h>
    #define mk make_pair
    
    using namespace std;
    typedef long long LL;
    const int maxn = 300000 + 1000;
    int n, m;
    pair<int, int> xx[maxn];
    vector<LL> v;
    vector<int> x[maxn];
    vector<int> y[maxn];
    map<pair<int, int>, int> p;
    int len;
    
    void solve(){
        int cnt = 0;
        for (int i = 0; i < n; i++){
            if (m <= 1) break;
            int tx = xx[i].first;
            int ty = xx[i].second;
            int lenx = x[tx].size(); //表示里面有几个y
            int leny = y[ty].size();//表示里面有几个x
            if (lenx < m) continue;
            if (leny < m) continue;
            //先找x上方的m-1个,里面放着y
            int py = lower_bound(x[tx].begin(), x[tx].end(), ty) - x[tx].begin();//在x的集合里面,y的位置
            if (py + m > lenx) continue;
            int px = lower_bound(y[ty].begin(), y[ty].end(), tx) - y[ty].begin();//在y这个集合里面,x的位置
            if (px + m > leny) continue;
            int posx = y[ty][px + m - 1];
            int posy = x[tx][py + m - 1];//this?
            if (p[mk(posx, posy)]){
                cnt++;
            }
        }
        printf("%d
    ", cnt);
    }
    
    int main(){
        int t; cin >> t;
        while (t--){
            scanf("%d%d", &n, &m);
            for (int i = 0; i < n; i++){
                LL a, b;
                scanf("%I64d%I64d", &a, &b);
                xx[i] = mk(a, b);
                v.push_back(a);
                v.push_back(b);
            }
            sort(v.begin(), v.end());
            v.erase(unique(v.begin(), v.end()), v.end());
            int lx = 0, ly = 0;
            for (int i = 0; i < n; i++){
                int tx = xx[i].first = lower_bound(v.begin(), v.end(), xx[i].first) - v.begin();
                int ty = xx[i].second = lower_bound(v.begin(), v.end(), xx[i].second) - v.begin();
                //printf("%d %d
    ", xx[i].first, xx[i].second);
                p[mk(tx, ty)] = 1;
                x[tx].push_back(ty);
                y[ty].push_back(tx);
                lx = max(lx, tx);
                ly = max(ly, ty);
            }
            for (int i = 0; i <= lx; i++){
                sort(x[i].begin(), x[i].end());
            }
            for (int i = 0; i <= ly; i++){
                sort(y[i].begin(), y[i].end());
            }
            solve();
            //初始化
            p.clear();
            v.clear();
            for (int i = 0; i <= lx; i++){
                x[i].clear();
            }
            for (int i = 0; i <= ly; i++){
                y[i].clear();
            }
            memset(xx, 0, sizeof(xx));
        }
        return 0;
    }
    View Code

    九:数学(链接:账号密码同上

    题意:对自然数列{1,2,3,4,5,6...}进行n次操作,每次操作有一个x,意思是前x个保留,后x个删去,再x个保留,后x个删去。。。形成新的序列,问n次操作后第n个数字。

    思路:逆序插入

    关键:逆序思想

  • 相关阅读:
    codeforces 459C Pashmak and Buses(模拟,组合数A)
    HDU 4639 Hehe(字符串处理,斐波纳契数列,找规律)
    HDU 1671 Phone List(字符处理)
    网页爬虫【原创】【开源】
    asp.net mvc 配合前端js的CMD模块化部署思想,小思路
    [转]阎宏博士的JAVA与模式
    [转]使用设计模式改善程序结构(三)
    [转]使用设计模式改善程序结构(二)
    [转]使用设计模式改善程序结构(一)
    html符号转换
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5647712.html
Copyright © 2020-2023  润新知