CSP-S模拟1

背景图太花哨了,所以我把它去掉了。

 

A. 斐波那契

我本来以为算到56就够了,数0数错了就很***,fibo要算到70

一开始还以为编号越大深度越小,然后发现题面上给的图都不满足……(交上去是90分,数据够水的)

就开始找深度,每跳一层查一遍深度TLE70,后来发现往上跳深度直接减1就行了。

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = -2;
const int N = 60;
const ll mod = 1e9 + 7;

ll fibo[70], f2[70], m;

inline ll read()
{
    ll 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;
}

inline ll getfa(ll x)
{
    ll y = upper_bound(f2+1, f2+N+1, x)-f2-1;
    return x - f2[y] + 1;
}

void init()
{
    fibo[1] = 1; fibo[2] = 1; fibo[3] = 1;
    for(int i=4; i<=N; i++)
    {
        fibo[i] = fibo[i-1] + fibo[i-2];
    }
    f2[1] = 1;
    for(int i=2; i<=N; i++)
    {
        f2[i] = f2[i-1] + fibo[i-1];
        if(f2[i] < 0) break;
    }
}

inline ll getdep(ll x)
{
    int ret = 0;
    while(x != 1)
    {
        x = getfa(x);
        ret++;
    }
    return ret;
}

int main()
{
    init();
    m = read();
    while(m--)
    {
        ll a = read(), b = read();
        ll depa = getdep(a), depb = getdep(b);
        while(a != b)
        {
            if(depa < depb) 
            {
                swap(a, b); swap(depa, depb);
            }
            a = getfa(a); depa--;
        }
        printf("%lld\n", a);
    }
  
    return 0;
}
View Code

 

B. 数颜色

暴力就可以有40分,写了个分块还写错了WA10,算了一个可持久化权值线段树的空间还以为不够用……

%%%wenqizhi1125 指出蓝书上分块的蒲公英那个题(求区间众数)的查找位置和这个题很相似。

本来对于lower_bound的返回值犹豫了半天,然后发现我想到的都是些蠢问题,比如lower_bound找的是大于等于的第一个,我以为查找一个比最小的数还小的东西会返回-1。

vector的sort也是这个格式。

关于相对位置为什么不会改变这个问题——交换的是相邻的两个啊,而且还颜色不一样。颜色一样当然可以直接换。

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = -2;
const int N = 3e5 + 6;
const ll mod = 1e9 + 7;

int n, m, ans, a[N];
vector<int> vec[N];

inline int read()
{
    ll 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 main()
{
    n = read(); m = read();
    for(int i=1; i<=n; i++)
    {
        a[i] = read();
        vec[a[i]].push_back(i);
    }
    while(m--)
    {
        int tp = read();
        if(tp == 1)
        {
            int l = read(), r = read(), c = read();
            int k1 = lower_bound(vec[c].begin(), vec[c].end(), l)-vec[c].begin();
            int k2 = upper_bound(vec[c].begin(), vec[c].end(), r)-vec[c].begin()-1;
            ans = k2 - k1 + 1;
            printf("%d\n", ans);
        }
        else 
        {
            int x = read(), c1 = a[x], c2 = a[x+1];
            int k = lower_bound(vec[c1].begin(), vec[c1].end(), x)-vec[c1].begin();
            vec[c1][k] = x + 1;
            k = lower_bound(vec[c2].begin(), vec[c2].end(), x+1)-vec[c2].begin();
            vec[c2][k] = x;
            swap(a[x], a[x+1]);
        }
    }
  
    return 0;
}
View Code

 

C. 分组

针对数据搞了一个部分分64:

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = 131099;
const int N = 5e4 + 3;
const ll mod = 1e9 + 7;

int n, k, a[maxn], pos[maxn], cnt;
bool f = 1;

inline int read()
{
    ll 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 main()
{
    n = read(); k = read();
    for(int i=1; i<=n; i++)
    {
        a[i] = read();
        if(a[i] > 2) f = 0;
    }
    if(f)
    {
        for(int i=1; i<=n; i++)
        {
            if(a[i] == 2) pos[++cnt] = i;
        }
        cnt--;
        if(k == 1)
        {
            printf("%d\n", cnt+1);
            for(int i=1; i<=cnt; i++)
            {
                printf("%d ", pos[i]);
            }
            printf("\n");
        }
        else 
        {
            if(cnt & 1)
            {
                printf("%d\n", cnt/2+1);
                for(int i=2; i<=cnt; i+=2)
                {
                    printf("%d ", pos[i]);
                }
                printf("\n");
            }
            else 
            {
                printf("%d\n", cnt/2+1);
                for(int i=1; i<=cnt; i+=2)
                {
                    printf("%d ", pos[i]);
                }
                printf("\n");
            }
        }
        exit(0);
    }
    //k = 1
    int r = n;
    for(int i=n; i>=1; i--)
    {
        for(int j=r; j>i; j--)
        {
            if(a[i] + a[j] == (int)pow((int)sqrt(a[i]+a[j]), 2)) 
            {
                r = i; pos[++cnt] = i; break;
            }
        }
    }
    if(k == 1)
    {
        printf("%d\n", cnt+1);
        for(int i=cnt; i>=1; i--)
        {
            printf("%d ", pos[i]);
        }
        printf("\n");
    }
    else 
    {
        printf("%d\n", cnt/2+1);
        if(cnt & 1)
        {
            for(int i=cnt-1; i>=1; i-=2)
            {
                printf("%d ", pos[i]);
            }
            printf("\n");
        }
        else 
        {
            for(int i=cnt; i>=1; i-=2)
            {
                printf("%d ", pos[i]);
            }
            printf("\n");
        }
    }
  
    return 0;
}
View Code

优化查找比较神奇,可以去枚举这个平方数,看看差值是不是在当前组出现过。

vector<int>().swap(fairy[a[q]]) 其实就是清空的意思。

Copy from %%%Varuxn

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = 131099;
const int N = 5e4 + 3;
const ll mod = 1e9 + 7;

int n, k, a[maxn], pos[maxn], cnt, fa[maxn<<1];
vector<int> fairy[maxn<<1];
bool v[maxn<<1];//不开二倍会WA

inline int read()
{
    ll 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 find(int x)
{
    if(x == fa[x]) return x;
    return fa[x] = find(fa[x]);
}

int main()
{
    n = read(); k = read();
    int r = n;
    for(int i=1; i<=n; i++)
    {
        a[i] = read();
    }
    if(k == 1)
    {
        for(int i=n; i>=1; i--)
        {
            bool flag = 1;
            //尽管找的是另一个单值,但是循环枚举到了和,不开二倍会导致数组越界!
            for(int j=1; j<=512; j++)
            {
                if(j*j >= a[i])
                {
                    if(v[j*j-a[i]])
                    {
                        flag = 0; break;
                    }
                }
            }
            if(!flag)
            {
                for(int j=i+1; j<=r; j++)
                {
                    v[a[j]] = 0;
                }
                pos[++cnt] = i;
                r = i;
            }
            v[a[i]] = 1;
        }
        printf("%d\n", cnt+1);
        for(int i=cnt; i>=1; i--)
        {
            printf("%d ", pos[i]);
        }
    }
    else 
    {
        for(int i=1; i<=(n<<1); i++)
        {
            fa[i] = i;
        }
        for(int i=n; i>=1; i--)
        {
            for(int j=1; j<=512; j++)
            {
                if(j*j >= a[i])
                {
                    if(fairy[j*j-a[i]].size())
                    {
                        for(int p=0; p<fairy[j*j-a[i]].size(); p++)
                        {
                            int now = fairy[j*j-a[i]][p];
                            if(find(now) == find(i))
                            {
                                for(int q=i+1; q<=r; q++)
                                {
                                    vector<int>().swap(fairy[a[q]]);
                                }
                                pos[++cnt] = i;
                                r = i;
                            }
                            else 
                            {
                                fa[find(i+n)] = find(now);
                                fa[find(now+n)] = find(i);
                            }
                        }
                    }
                }
            }
            fairy[a[i]].push_back(i);
        }
        printf("%d\n", cnt+1);
        for(int i=cnt; i>=1; i--)
        {
            printf("%d ", pos[i]);
        }
    }
  
    return 0;
}
View Code

 

posted @ 2022-09-03 19:46  Catherine_leah  阅读(19)  评论(0编辑  收藏  举报
/* */