暑假第二十五测

以后WA了T了看数组;

暑假四次数组下标超界,多次数组开小,暂时没有访问到负下标

题解;

第一题;这道题可以转换为颜色相同的点缩成一个点,每次可以将两个点合并成同一点,问最少几次将所有点合并成一个点;

开始想到并查集+贪心合并度数最多的并查集,但这样是有问题的,比如度数一样时,选择的先后顺序是有影响的;

正解:缩点+找直径,如果是一条黑白相间的链,就是点数/2, 而树上任何一条直径都会有一个点经过直径,我们从交点开始往外延伸,发现最长延伸就是直径本身;

思想:从特殊到一般

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5 + 10;
#define ex(i, u) for(int i = h[u]; i; i = G[i].nxt)
int h[M], col[M], tot, fa[M], rec[M], vec[M], dep[M];
struct edge{int nxt, v;}G[M * 2];
void add(int u, int v){
    G[++tot].nxt = h[u]; h[u] = tot; G[tot].v = v;
}
int find(int u){
    if(u == fa[u])return u;
    return fa[u] = find(fa[u]);
}
void uni(int u, int v){
    fa[find(u)] = find(v);
}
int read(){
    int x = 0,f = 1; char c = getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*=f;
}
int rt, res;
void dfs(int u, int f){
    //fprintf(stderr , "%d %d\n", u, f);
    dep[u] = dep[f] + 1;
    ex(i, u){
        int v = G[i].v;
        if(v == f)continue;
        dfs(v, u);
    }
    if(dep[u] > dep[res])res = u;
}

int main(){
    freopen("color.in","r",stdin);
    freopen("color.out","w",stdout);
    int T;
    scanf("%d", &T);
    while(T--){
        int n = read();
        for(int i = 1; i <= n; i++)
            col[i] = read(), h[i] = 0, fa[i] = i;
        tot = 0;
        int u, v, p = 0;
        for(int i = 1; i < n; i++){
            u = read(), v = read();
            if(col[u] == col[v])uni(u, v);
            else vec[++p] = u, rec[p] = v;
        }
        for(int i = 1; i <= p; i++){
            int x = find(rec[i]), y = find(vec[i]);
            add(x, y), add(y, x); //fprintf(stderr, "%d %d\n", y, x);
        }
        for(int i = 1; i <= n; i++)
            if(i == find(i)){
                res = rt = 0;
                memset(dep, 0, sizeof(dep));
                dfs(i, 0);
                memset(dep, 0, sizeof(dep));
                rt = res;
                dfs(rt, res = 0);
                break;
            }
        printf("%d\n", dep[res]/ 2);
    }
    return 0;
}

第二题:模拟,我们发现很多路径是重复的,所以要想办法避免;又发现格子最多有150^2个,所以我们只需要记录格子是否被访问;每次从一个格子暴力沿八个方向走,如果到一个格子也有相同的方向,如果该格子走的远,就停下来,让这个格子完成任务,如果该格子走的不如当前远,那么他的延伸就是废的,去掉;

每个格子最多朝8个方向时被重复,就是O(300*300*8);

这道题我数组开的N,循环的时候也循环到N, 开了O2全WA,都学这么久了,怎么还在犯这种低级错误!!!

而且上次考试又是少写了一个等号全WA!!!该好好练练码力了;

#include<bits/stdc++.h>
using namespace std;
const int N = 306;
int zl[10][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}};
int go[10][2] = {{0, 0}, {2, 8}, {1, 3}, {2, 4}, {3, 5}, {4, 6}, {5, 7}, {6, 8}, {1, 7}};
int n;
int mp[N+11][N+11][10], a[50];
bool vis[N+11][N+11], done[N+11][N+11];
struct node{int x,y,dep,fx;};
void bfs(){
    queue <node> q;
    q.push((node){152, 152, 1, 1});
    mp[152][152][1] = 1;

    while(!q.empty()){
        node u = q.front(); q.pop();
        done[u.x][u.y] = 1;
        int i = u.fx;
        int x = u.x + zl[i][0] * a[u.dep], y = u.y + zl[i][1] * a[u.dep];
        if(a[mp[x][y][go[i][0]]] < a[u.dep + 1]){
            mp[x][y][go[i][0]] = u.dep + 1;q.push((node){x, y, u.dep + 1, go[i][0]});
        }
        if(a[mp[x][y][go[i][1]]] < a[u.dep + 1]){
            mp[x][y][go[i][1]] = u.dep + 1;q.push((node){x, y, u.dep + 1, go[i][1]});
        }
    }
}

void work(){
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= N; j++){
            if(!done[i][j])continue;
            for(int k = 1; k <= 8; k++){
                if(mp[i][j][k]){
                    //printf("%d %d %d %d\n", i, j, k, mp[i][j][k]);
                    int x = i, y = j;
                    for(int z = 1; z <= a[mp[i][j][k]]; z++){
                        x += zl[k][0], y += zl[k][1];
                        if(a[mp[x][y][k]] > a[mp[i][j][k]] - z)break;
                        else mp[x][y][k] = 0;
                        vis[x][y] = 1;
                    }
                    vis[i][j] = 1;
                }
            }
        }

}

int main(){
    freopen("grow.in","r",stdin);
    freopen("grow.out","w",stdout);
    //int cc=clock();
    int ans = 0;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
    a[1]--;
    bfs();
    work();
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= N; j++)if(vis[i][j])ans++;//,printf("%d %d\n",i,j);
    printf("%d\n", ans);
    //int tt=clock();
    //cout<<tt-cc;
}

第三题:dp,定义状态 :

0  1    2        3         4

#  2    20    201    2017

dp[s][t]表示从状态s转移到状态t的最少删除字符,我们枚举中间状态r, dp[s][t] = min(dp[s][r] + dp[r][t]);

但不可能每次询问都做一次,所以用线段树做,转移相当于线段树合并;代码可以学习一下

#include<bits/stdc++.h>
using namespace std;
const int inf = 1e8, M = 1e5 + 10;
int n;
char s[M];
struct Info{//没有放在Node里是因为重载运算符不能返回一个指针
    int tr[5][5];
    // 0 1  2  3   4
    // $ 2 20 201 2017
    void init(int v){
        memset(tr, 0x3f, sizeof(tr));
        if(v == 3 || v == 4 || v == 5 || v == 8 || v == 9){
            for(int i = 0; i < 5; i ++)tr[i][i] = 0;
        }

        if(v == 2){
            tr[0][0] = 1;
            tr[0][1] = 0;
            tr[1][1] = tr[2][2] = tr[3][3] = tr[4][4] = 0;
        }

        if(v == 0){
            tr[1][2] = 0;
            tr[1][1] = 1;
            tr[0][0] = tr[2][2] = tr[3][3] = tr[4][4] = 0;
        } 

        if(v == 1){
            tr[2][3] = 0;
            tr[2][2] = 1;
            tr[0][0] = tr[3][3] = tr[4][4] = tr[1][1] = 0;
        }

        if(v == 7){
            tr[3][3] = 1;
            tr[3][4] = 0;
            tr[1][1] = tr[4][4] = tr[2][2] = tr[0][0] = 0;
        }

        if(v == 6){
            tr[3][3] = tr[4][4] = 1;
            tr[0][0] = tr[1][1] = tr[2][2] = 0;
        }
    }
};
struct Node{
    Info info;
    Node *ls, *rs;
}pool[(M << 2)], *tail = pool, *root; 

Info operator + (const Info &a, const Info &b){//重载运算符写法
    Info rt;
    memset(&rt, 0x3f, sizeof(rt));//取地址
    for(int i = 0; i < 5; i++)
        for(int j = 0; j < 5; j++)
            for(int k = i; k <= j; k++)
                rt.tr[i][j] = min(rt.tr[i][j], a.tr[i][k] + b.tr[k][j]);
    /*for(int i = 0;i<5;i++)for(int j=0; j<5;j++)
    printf("%d %d %d\n",i,j,zero->tr[i][j]);puts("");*/
    return rt;
}

Node * build(int lf = 1, int rg = n){
    Node *nd = ++tail;
    if(lf == rg)nd->info.init(s[lf - 1] - ‘0‘);
    else {
        int mid = (lf + rg) >> 1;
        nd->ls = build(lf, mid);
        nd->rs = build(mid + 1, rg);
        nd->info = nd->ls->info + nd->rs->info;
    }
    return nd;
}

Info query(int L, int R, Node * nd = root, int lf = 1, int rg = n){
    if(lf >= L && rg <= R)return nd->info;
    int mid = (lf + rg) >> 1;
    if(L > mid)return query(L, R, nd->rs, mid + 1, rg);
    else if(R <= mid)return query(L, R, nd->ls, lf, mid);
    else return query(L, R, nd->ls, lf, mid) + query(L, R, nd->rs, mid + 1, rg);
}
int Query(int l, int r){
    Info ans = query(l, r);
    return ans.tr[0][4] < inf ? ans.tr[0][4] : -1;
}

int main(){
    freopen("year.in","r",stdin);
    freopen("year.out","w",stdout);
    scanf("%s", s);
    n = strlen(s);
    root = build();
    int q, l, r;
    scanf("%d", &q);
    while(q--){
        scanf("%d%d", &l, &r);
        printf("%d\n", Query(l, r));
    }

}

原文地址:https://www.cnblogs.com/EdSheeran/p/9538252.html

时间: 2024-10-11 00:22:26

暑假第二十五测的相关文章

暑假第二十四测

题解: 第一题:二分+贪心:二分距离上限,两端的人能从两端取就从两端取,这样可以为中间的做贡献: #include<bits/stdc++.h> using namespace std; const int M = 10005; int a[M], b[M], pos[M], x, n, m; bool id[M]; #define ll long long inline int ab(int a, int b){ if(a > b)return a - b; return b - a;

暑假第二十六测

今天又考的奇差 题解: 第一题: 这么简单一道题我想了好久,智商实在是下线了: #include<bits/stdc++.h> using namespace std; int main(){ freopen("shortway.in","r",stdin); freopen("shortway.out","w",stdout); int n, k; scanf("%d%d", &n,

暑假第二十九测

第三题换成能否得到x, 可以1, 不可以-1 题解: 第一题:打表找规律: 打表发现a是:1 1 2 2 3 4 4 4 5 6 6 7 8 8 8 8 9-- 对于每一项Ai = i拆分成质因数中有多少个2 + 1:如果把桶也给打出来,就发现他是这样的: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 2 + 4 + 6 + 8 +  4  + 8 +  8 + 即2^i的等差数列,所以对一个数m我们就很容易确定他前面的数的和: 但是对于一个位置我们怎么找到他对应的m呢? 把上

centos lamp/lnmp阶段复习 第二十五节课

centos  lamp/lnmp阶段复习   第二十五节课 上半节课 下半节课 f

第二十五天 慵懒的投射在JDBC上的暖阳 —Hibernate的使用(四)

6月4日,晴天."晴日暖风生麦气,绿阴幽草胜花时."      "道"是只有中国人才懂得并孜孜以求的特殊的宇宙存在感的体验.全世界只有中文才能阐释"道"的全部涵义.然而所谓阐释,并不重在定义,更多的还是感受. "道"既在"虚无"之内,又超越了"虚无",成为中国文化最平常但又最玄妙的一种境界. 老庄认为:道是宇宙的本体,即是宇宙万物的老祖宗.    老外认为:Tao is the sour

第二十五课:超越抽象极限

1.一个阶跃输入,后面接戴维南电阻,测量点Vout,之后接其他设计电路,末端开路 理论上在同一时刻Vout也发生阶跃(例如 0到5V) 实际上,在t=0是,输出上升到一半,持续一段时间才会继续上升到5V 这是因为当导线非常长时,需要考虑信号传输时间 脉冲到达末端返回到Vo,Vo得到一个回波,两个2.5V相加就达到5V 这个阻抗对于多数导线都等于50欧姆,称之为特性阻抗 解决方法:换短的导线: 改变时钟信号 2.同一个电压对多个反相器供电 前一个反相器在上端导通时,通过的电流变化会在电感上产生压降

NeHe OpenGL教程 第二十五课:变形

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十五课:变形 变形和从文件中加载3D物体: 在这一课中,你将学会如何从文件加载3D模型,并且平滑的从一个模型变换为另一个模型. 欢迎来到这激动人心的一课,在这一课里,我们将介绍模型的变形.需要注意的是各个模型必须要有相同的顶点,

Gradle 1.12用户指南翻译——第二十五章. Scala 插件

其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/userguide/userguide.html. 另外,Android 手机用户可通过我写的一个程序浏览文档,带缓存功能的,目前

centos NFS/FTP服务配置 第二十五节课

centos  NFS/FTP服务配置   第二十五节课 上半节课 下半节课 f