附:官方题解传送门

D. Pair of Topics

离散化+树状数组,O(2n*log(2n))的复杂度,实测运行841ms。

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,a[N],b[N],d[2*N],t[2*N],num1[2*N],num2[N];
struct node
{
    int tr[2*N];
    int lowbit(int x)
    {return x&(-x);}
    void add(int pos,int k)
    {
        for(int i=pos;i<=2*n;i+=lowbit(i))
            tr[i]+=k;
    }
    int sum(int pos)
    {
        int s=0;
        for(int i=pos;i;i-=lowbit(i))
            s+=tr[i];
        return s;
    }
}T1,T2;//两个树状数组
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        cin>>b[i];
        d[i]=a[i]-b[i];
        d[i+n]=-d[i];//相反数
        t[i]=d[i];//t是d的备份
        t[i+n]=d[i+n];
    }
    stable_sort(t+1,t+2*n+1);
    for(int i=1;i<=2*n;i++)
    {
        int k=lower_bound(t+1,t+2*n+1,d[i])-t;
        num1[i]=k;//num是d离散化后的数组(总共)
        T1.add(num1[i],1);
        if(i>n)
        {
            num2[i-n]=k;
            T2.add(num2[i-n],1);
        }
    }
    long long ans=0;
    for(int i=1;i<=n;i++)
    {
        T1.add(num1[i],-1);
        T1.add(num2[i],-1);
        T2.add(num2[i],-1);
        int s1=T1.sum(2*n)-T1.sum(num2[i]);//总共比num2[i]大的数的个数
        int s2=T2.sum(2*n)-T2.sum(num2[i]);//在相反数的数组中比num2[i]大的数的个数
        ans+=s1-s2;
    }
    printf("%lld\n",ans);
    return 0;
}

后来看了大佬们的代码,发现这题我又想复杂了,没必要上树状数组维护。
找到公式,类似尺取计数即可。O(n*logn)的复杂度,实测运行156ms。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll const maxn=2e5+5;
ll n,a[maxn],b[maxn],c[maxn],l,r,ans;
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;++i)
        scanf("%lld",&a[i]);
    for(int i=1;i<=n;++i)
        scanf("%lld",&b[i]);
    for(int i=1;i<=n;++i)
        c[i]=a[i]-b[i];
    sort(c+1,c+1+n);
    l=1,r=n,ans=0;
    while(1)
    {
        if(c[l]+c[r]>0){ans+=r-l;r--;}
        else l++;
        if(r==l) break;
    }
    cout<<ans<<endl;
    return 0;
}

C. Frog Jumps

0是起点,n+1是终点,每次根据当前位置是L还是R可以选择向后或向前跳[1,d]步(不能超过范围),特别地,对于0位置和n+1位置,我们可以当作是R。

贪心,显然跳到L就只能往后退直到为R,那么不如直接刚开始就跳到刚才回退到的R,不用多走这些冤枉路,所以策略就是每次只跳R,因此我们只需要找相邻的R距离最大值,这样就能保证每次都能跳到R,一直踩着R前进,这是最短的路径。

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int T;
char s[N];
int main()
{
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--)
    {
        cin>>s+1;
        int pos=0;
        int n=strlen(s+1);
        s[n+1]='R';
        int mx=0;
        for(int i=1;i<=n+1;i++)
            if(s[i]=='R'){mx=max(mx,i-pos);pos=i;}
        printf("%d\n",mx);
    }
    return 0;
}

B. Yet Another Palindrome Problem

这个很简单,找长度为3的回文就行,但是没注意特判三个数均相等的情况,被hack了

#include <bits/stdc++.h>
using namespace std;
const int N=5050;
int T,n,a[N],vis[N];
bool judge()
{
    for(int i=1;i<=n;i++)
    {
        if(vis[a[i]]&&i-vis[a[i]]>=2)return 1;
        vis[a[i]]=i;
    }
    return 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        memset(vis,0,sizeof(vis));
        if(judge())printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

hack:
1 3
1 1 1
正确输出:YES

修改后的AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N=5050;
int T,n,a[N],vis[N];
bool judge()
{
    for(int i=1;i<=n;i++)
    {
        if(vis[a[i]]&&i-vis[a[i]]>=2||(i-1>=1&&i+1<=n&&a[i]==a[i-1]&&a[i]==a[i+1]))return 1;
        //注意特判三个连续的数相等的情况
        vis[a[i]]=i;
    }
    return 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        memset(vis,0,sizeof(vis));
        if(judge())printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

A. Yet Another Tetris Problem

类似俄罗斯方块,但是如果只有一列,那么它自己也会消失到高度为0。
不难发现,只要高度全部为奇数或者全部为偶数即可全部消去。

#include <bits/stdc++.h>
using namespace std;
int a[110],n,T;
bool judge()
{
    int f1=0,f2=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]&1)f1++;//奇数
        else f2++;//偶数
        if(f1&&f2)return 0;
    }
    return 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        if(judge())printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}