綠題自嗨1

Catherine_leah發表於2024-12-07

遊戲玩多了,後悔了,打算戒一下游戲,於是我們可以愉快地繼續做題了

如果這篇裡的題您一眼秒了請不要嘲笑我,我會哭的

好叭其實我已經哭了因為我知道您已經秒掉它們了

P1119 災後重建

試圖每次在圖裡加邊。把邊按照時間排序,時間到了就可以這條邊加到圖裡了,同時連著這條邊的兩個點也可以做Floyed的中轉點了,但是這樣會有不少重複運算,由於邊是實時新增的,還不能設vis標記已經訪問過的點。但其實題意就是直接加點,邊本來就可以用,所以我繞遠了。

TLE 80
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 204;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int n, m, q;
int w[maxn][maxn], t[maxn];

struct node 
{
    int u, v, w;
    bool operator < (const node &T) const 
    {
        return t[u] < t[T.u];
    }
}b[20000];

void floyed(int k)
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            if(w[i][j] > w[i][k] + w[k][j])
            {
                w[i][j] = w[i][k] + w[k][j];
            }
        }
    }
}

int main()
{
    n = read(); m = read();
    for(int i=0; i<n; i++) t[i] = read();
    for(int i=1; i<=m; i++)
    {
        int u = read(), v = read(), h = read();
        if(t[u] < t[v]) swap(u, v);//相對較大的一項最小
        b[i].u = u; b[i].v = v; b[i].w = h;
    }
    sort(b+1, b+1+m);
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            w[i][j] = 1e9;
        }
        w[i][i] = 0;
    }
    q = read(); int j = 1;
    for(int i=1; i<=q; i++)
    {
        int x = read(), y = read(), tnow = read();
        while(j <= m && t[b[j].u] <= tnow)
        {
            w[b[j].u][b[j].v] = w[b[j].v][b[j].u] = min(w[b[j].u][b[j].v], b[j].w);
            //j++; //ntc = 0;
            floyed(b[j].v);
            floyed(b[j].u);
            j++;//我加早了
        }
        if(w[x][y] == 1e9) printf("-1\n");
        else printf("%d\n", w[x][y]);
    }

    return 0;
}

然後改成新增點就能過了。不過加點和加邊不同的是需要判斷詢問的時刻兩端是否修好,不過這個題目裡也描述了,emmm可見我是不會讀題的。

code
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 204;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int n, m, q;
int w[maxn][maxn], t[maxn];

void floyed(int k)
{
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            if(w[i][j] > w[i][k] + w[k][j])
            {
                w[i][j] = w[i][k] + w[k][j];
            }
        }
    }
}

int main()
{
    n = read(); m = read();
    for(int i=0; i<n; i++) t[i] = read();
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++) w[i][j] = 1e9;
        w[i][i] = 0;
    }
    for(int i=1; i<=m; i++)
    {
        int u = read(), v = read(), h = read();
        w[u][v] = w[v][u] = min(w[u][v], h);
    }
    q = read(); int j = 0;
    for(int i=1; i<=q; i++)
    {
        int x = read(), y = read(), tnow = read();
        while(j < n && t[j] <= tnow)
        {
            floyed(j); j++;
        }
        if(w[x][y] == 1e9 || t[x] > tnow || t[y] > tnow) printf("-1\n");
        else printf("%d\n", w[x][y]);
    }

    return 0;
}

P1121 環狀最大兩段子段和

WA 80
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 4e5 + 7;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int n, a[maxn], sum[maxn], ans=-1e9, posl, posr, ty;
int l, r, q[maxn];

int main()
{
    n = read();
    for(int i=1; i<=n; i++) a[i] = read();
    for(int i=1; i<=n; i++) a[i+n] = a[i];
    for(int i=1; i<=n+n; i++) sum[i] = sum[i-1] + a[i];
    l = 1; r = 1;
    q[1] = 0; 
    for(int i=1; i<=n+n; i++)//先找到最大的一段
    {
        while(l <= r && q[l] < i - n) l++;
        if(ans < sum[i] - sum[q[l]])
        {
            posl = q[l] + 1; posr = i; ans = sum[i] - sum[q[l]];
        }
        while(l <= r && sum[q[r]] >= sum[i]) r--;
        q[++r] = i;
    }
    int mx = min(n+n, posl+n-1), ans2 = -1e9;
    l = 1; r = 1; q[1] = posr;
    for(int i=posr+1; i<=mx; i++)
    {
        ans2 = max(ans2, sum[i] - sum[q[l]]);
        while(l <= r && sum[q[r]] >= sum[i]) r--;
        q[++r] = i;
    }
    if(posl == posr) ty = ans + ans2;
    else ty = max(ans, ans+ans2);
    printf("%d", ty);

    return 0;
}

先斷環成鏈再滑動視窗求最大值,在第一次的基礎上再求一次,然後錯了。或許是因為這種東西不能貪心。

然後……鶴了一下I_AM_HelloWord的題解……把 i 之前的最大子段和 i 之後的最大子段相加就可以得到沒有環的答案,而有環的區別就是可以首尾相連,沒選的部分相當於不成環情況下的最小兩段子段,總和減掉最小兩段子段的結果就是另一種可能的情況。如果只有1個正數(其實應該是非負數?)倒過來會出現首尾全選再作差也就是隻選了一個數的情況需要特判。

code
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 7;
const int INF = 0x3f3f3f3f;//1061109567

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int n, sum, tot;
int f[maxn], g[maxn], a[maxn];

int query()//原來兩個最大子段和可以這麼算!!抄完我終於明白了(bushi)
{
    int ans = -INF;
    for(int i=1; i<=n; i++) f[i] = max(f[i-1], 0) + a[i];
    for(int i=n; i>=1; i--) g[i] = max(g[i+1], 0) + a[i];
    for(int i=1; i<=n; i++) f[i] = max(f[i-1], f[i]);
    for(int i=n; i>=1; i--) g[i] = max(g[i+1], g[i]);
    for(int i=1; i<n; i++) ans = max(ans, f[i] + g[i+1]);
    return ans;
}

int main()
{
    n = read();
    memset(f, ~0x3f, sizeof(f));//-1061109568
    memset(g, ~0x3f, sizeof(g));
    for(int i=1; i<=n; i++) 
    {
        a[i] = read(); sum += a[i]; tot += a[i] >= 0;
    }
    int t1 = query();
    if(tot == 1) printf("%d", t1);
    else 
    {
        for(int i=1; i<=n; i++) a[i] = -a[i];
        int t2 = sum + query();
        if(!t2) t2 = -INF;
        printf("%d", max(t1, t2));
    }

    return 0;
}

P1124 檔案壓縮

NULL
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e4 + 7;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int n;
char s[maxn];
struct node 
{
    char l, r;//首字母和尾字母
    int t;//順序
    bool operator < (const node &T) const 
    {
        if(l == T.l) return t < T.t;
        return l < T.l;
    }
}xl[maxn];

int main()
{
    n = read();
    scanf("%s", s);
    for(int i=0; i<n; i++)
    {
        xl[i+1].l = s[i];
        xl[i+1].r = s[(i+n-1)%n];
        xl[i+1].t = i;
    }
    sort(xl+1, xl+1+n);
    for(int i=1; i<=n; i++) printf("%c %c\n", xl[i].l, xl[i].r);
    printf("\n");
    for(int i=1; i<=n; i++)
    {
        printf("%c", xl[i].r);
    }
    printf("\n");
    for(int i=1; i<=n; i++)
    {
        if(xl[i].t == 1) 
        {
            printf("%d", i); break;
        }
    }

    return 0;
}

本來打算寫出正向的求法再逆過來,然後不會做了。如果有很小的資料的話我只想到了全排列列舉,小菜是這樣的。

然後忽然有思路了,感覺是對的但是隻有10分,疑似出現了各種越界……(放在這只是為了存檔,沒有儲存程式碼的習慣,晚飯後再研究)

WA 10
 #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e4 + 7;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int n, p;
char s1[maxn], s[maxn], c[maxn];
vector<int> pos[30];

int main()
{
    n = read();
    scanf("%s", s1);
    p = read();
    s[0] = s1[p-1];
    memcpy(c, s1, sizeof(c));
    //printf("%s", c);
    sort(c, c+n);
    for(int i=n-1; i>=0; i--)
    {
        if(i == p-1) continue;
        pos[s1[i]-'a'+1].push_back(i);
        //printf("pos[%c].push_back(%d)\n", s1[i], i);
    }
    int r = p-1;
    for(int i=0; i<n; )
    {
        s[++i] = c[r];
        //printf("c[%d] = %c\n", r, c[r]);
        int l = pos[c[r]-'a'+1].size()-1;
        //printf("l = %d\n", l);
        l = pos[c[r]-'a'+1][l];
        //printf("r = %d\n", r);
        pos[c[r]-'a'+1].pop_back();
        r = l;
        //s[++i] = s1[r];
    }
    s[n] = '\0';
    printf("%s", s);

    return 0;
}

相關文章