1. 程式人生 > 實用技巧 >POI題目選做

POI題目選做

POI題目選做

[POI2015]WIL-Wilcze doły

題意

給定一個長度為 n 的序列,你有一次機會選中一段連續的長度不超過 d 的區間,將裡面所有數字全部修改為 0。請找到最長的一段連續區間,使得該區間內所有數字之和不超過 p

題解

顯然長度為D時只會更優,尺取法列舉,單調佇列維護被刪除的一段

#include<bits/stdc++.h>

using namespace std;

#define LL long long

inline LL read()
{
    LL f = 1,x = 0;
    char ch;
    do
    {
        ch 
= getchar(); if(ch == '-') f = -1; }while(ch < '0'||ch > '9'); do { x = (x<<3) + (x<<1) + ch - '0'; ch = getchar(); }while(ch >= '0'&&ch <= '9'); return f*x; } const int MAXN = 2000000 + 5; LL n,p,d; LL sum[MAXN],a[MAXN]; LL ans; LL q[MAXN],head
= 1,tail; inline LL calc(LL x) { return sum[x] - sum[x-d]; } int main() { n = read(),p = read(),d = read(); for(int i=1;i<=n;i++) a[i] = read(),sum[i] = sum[i-1] + a[i]; ans = d; q[++tail] = d; int l = 1; for(int i=d+1;i<=n;i++) { while(head <= tail && calc(i) > calc(q[tail])) tail--; q[
++tail] = i; while(head <= tail && sum[i] - sum[l-1] - calc(q[head]) > p) { l++; while(head <= tail && l >q[head] - d + 1) head++; } ans = max(ans, 1LL * i - l + 1); } cout << ans << endl; }
View Code

[POI2012]LIT-Letters

題意

給出兩個長度相同的的只含大寫字母的字串 a,b

每次可以交換相鄰字元,求a到b的最小交換次數

題解

火柴排隊弱化版?

顯然逆序對

#include<bits/stdc++.h>

using namespace std;

#define LL long long

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

const int MAXN = 1000000 + 5;

int n;
char s[MAXN];
int a[MAXN];
queue<int>Q[30];
LL c[MAXN];
inline int lowbit(int x)
{
    return x&(-x);
}

inline LL Query(LL x)
{
    LL res = 0;
    while(x)
    {
        res += c[x];
        x -= lowbit(x);
    }
    return res;
}

inline void update(int x,int v)
{
    while(x <= n)
    {
        c[x] += v;
        x += lowbit(x);
    }
}

int main()
{
    n = read();
    scanf("%s",s+1);
    for(int i=1;i<=n;i++) a[i] = s[i]  - 'A';
    scanf("%s",s+1);
    for(int i=1;i<=n;i++) Q[s[i] -'A'].push(i);
    for(int i=1,cur;i<=n;i++) cur = a[i],a[i] = Q[cur].front(),Q[cur].pop();
    LL ans = 0;
    for(int i=1;i<=n;i++)
    {
        ans += i - 1 - Query(a[i]);
        update(a[i],1);
    }
    cout << ans << endl;
}
View Code