题目

T1

hdu5881

思路

看到样例和数据范围就明白了些什么。(b - a)/2 + 1。但是需要\(特判!!!!\)

代码

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
ll read() {
    ll 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;
}
ll a,b; 
int main() {
    freopen("lock.in","r",stdin);
    freopen("lock.out","w",stdout);
    while(cin>>a>>b) {
        if(b <= 1) {
            puts("0");
            continue;
        }
        if(b <= 2) {
            puts("1");
            continue;
        }
        int now = 0;
        if(a == b || a == b - 1) {
            puts("2");
            continue;
        }
        if(a > 1) now  = 1;
        cout<<(b-a)/2 + now<<endl;
    }
    return 0;
}

T2

0分思路

一开始的思路是先处理一下前缀和,然后二分长度。然后预处理出每一个点和其之前的b个点的权值和。然后去check当前长度是否能满足sum[i] - sum[l] - a[i] <= p a[i] 为预处理出的数组。然后还需要用一个st表来维护一下a数组的区间最值。然后MLE了、、、

100分思路

这个题的正解是用双指针 + 单调队列。和上面一样先预处理出a数组和sum数组。然后用双指针尽可能扩大区间长度,并且用单调队列维护处a数组的最大值。

代码

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 2000000 + 100;
ll read() {
    ll 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;
}
ll sum[N],a[N];
int q[N],head = 1,tail;
int ans = -1;
int main() {
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    int n = read(); ll p = read(); int d = read();  
    for(int i = 1;i <= n;++i) sum[i] = sum[i - 1] + read();
    for(int i = 1; i<= n;++i) a[i] = sum[i] - sum[max(0,i - d)];
    int ans = 0;
    int l = 0;
    for(int r = 1;r <= n;++r) {
        while(a[q[tail]] <= a[r] && tail >= head) tail--;
        q[++tail] = r;
        while(sum[r] - sum[l] - a[q[head]] > p && l < r) {
            l++;
            while(tail >= head && q[head] < l + d) head++;
        }
        if(sum[r] - sum[l] - a[q[head]] <= p) ans = max(ans,r - l);
    }
    cout<<ans;
    return 0;
}

T3

思路

\(n_3\)过1000

代码

#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
typedef long long ll;
map<int,int>ma;
ll read() {
    ll 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 a[N][N],b[N],tmp[N];
int n,k,now;
void lisan() {
    for(int i = 1;i <= n; ++i) tmp[i] = b[i];
    sort(tmp + 1,tmp + n + 1);
    ma[tmp[1]] = ++now;
    for(int i = 2;i <= n;++i) {
        if(tmp[i] != tmp[i - 1])
            ma[tmp[i]] = ++now;
    }
    for(int i = 1;i <= n;++i) b[i] = ma[b[i]];
}
void BF1() {
    for(int i = 1;i <= n;++i) b[i] = read();
    lisan();
    for(int i = 1;i <= now;++i)
        for(int j = 1;j < i; ++j)
            a[i][j] = 1;
    tmp[++n] = 0x7fffffff;
    for(int i = 1;i <= k;++i) {
        int l = read(),r = read();
        l = ma[tmp[upper_bound(tmp + 1,tmp + n + 1,l) - tmp]];
        r = ma[tmp[upper_bound(tmp + 1,tmp + n + 1,r) - tmp - 1]]; 
        for(int j = l;j <= r;++j) {
            for(int k = l;k < j;++k) {
                a[k][j] ^= 1;
                a[j][k] ^= 1;
            }
        }
    }
    ll ans = 0;
    for(int i = 1;i <= now;++i) {
        for(int j = 1;j < i;++j) {
            for(int k = 1;k < j;++k) {
                if(a[i][j] == a[j][k] && a[i][j] == a[k][i]) ans ++;
            }
        }
    }
    cout<<ans;
} 
int main() {
    freopen("fight.in","r",stdin);
    freopen("fight.out","w",stdout); 
    n = read() ,k = read();
    if(k == 0) {
        puts("0");
        return 0;
    }
    BF1();
    return 0;
}

总结

预计得分:100 + 100 + 30 = 230
实际得分:80 + 0 + 70 = 150
T1还有一些特殊情况需要特判没考虑到,T2空间算错了,瞬间少了120分。然后T3能过70真的神奇

一言

你太善良了,这个世界会把你啃得尸骨无存。 ——生活大爆炸