uestc summer training #2

A

B

签到题

D

模拟题

F

给你一个中序遍历 和每个点的权值 问你存不存在一颗树使得每个节点的祖先和它的权值是互质的

解:

质因数分解+分治模拟

因为中序遍历有个特点 如果一个点是一个子树的根的话 左儿子都在左边 右儿子都在右边

所以要求互质的是一段区间 用GCD来做的话肯定会超时 我们给每个合数一个leftprime表示该合数质因数分解后最小的质数

首先我们从左到右枚举 维护每个质数所到的最右边 更新每个合数的答案 再反过来从右到左做一次

然后模拟树分治找到根递归地看能不能构造树

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 1e6 + 5, MAXM = 1e5 + 5;
const int MAXQ = 100010;
//int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
/*inline void addedge(int u, int v, ll c)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        cost[tot] = c;
        Head[u] = tot;
}*/
inline void read(int &v)
{
        v = 0;
        char c = 0;
        int p = 1;
        while (c < '0' || c > '9')
        {
                if (c == '-')
                {
                        p = -1;
                }
                c = getchar();
        }
        while (c >= '0' && c <= '9')
        {
                v = (v << 3) + (v << 1) + c - '0';
                c = getchar();
        }
        v *= p;
}
const int N = 10000000 + 5;
int MAXX = -1;
bool flagsum;
int ptot = 0;
int num[N];
int father[N];
int prime[N];
bool check[N];
int fanwei[N];
int leftprime[N];
int lans[N], rans[N];
void Euler()
{
        ll now;
        for (int i = 2; i <= MAXX; i ++)
        {
                if (!check[i])
                {
                        prime[ptot ++] = i;
                }
                for (int j = 0; j < ptot; j ++)
                {
                        now = 1LL * prime[j] * i;
                        if (now > MAXX)
                        {
                                break;
                        }
                        check[now] = 1;
                        leftprime[now] = prime[j];
                        if (i % prime[j] == 0)
                        {
                                break;
                        }
                }
        }
}
bool get_ans(int fa, int l, int r)
{
        int flag = 0;
        if (l > r)
        {
                return true;
        }
        int aim;
        int len = (r - l - 1) / 2 + ((r - l - 1) & 1);
        for (int i = 0; i <= len; i++)
        {
                aim = l + i;
                if (lans[aim] < l && rans[aim] > r)
                {
                        //cout << fa << " " << l << " " << r << " " << i << endl;
                        //cout << lans[i] << " " << rans[i] << endl;
                        flag = 1;
                        flag = flag && get_ans(aim, l, aim - 1) && get_ans(aim, aim + 1, r);
                        if (flag)
                        {
                                father[aim] = fa;
                                return true;
                        }
                        else
                        {
                                return false;
                        }
                }
                aim = r - i;
                if (lans[aim] < l && rans[aim] > r)
                {
                        //cout << fa << " " << l << " " << r << " " << i << endl;
                        //cout << lans[i] << " " << rans[i] << endl;
                        flag = 1;
                        flag = flag && get_ans(aim, l, aim - 1) && get_ans(aim, aim + 1, r);
                        if (flag)
                        {
                                father[aim] = fa;
                                return true;
                        }
                        else
                        {
                                return false;
                        }
                }
        }
        return false;
}
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);

        int n;
        int cnt;
        read(n);
        for (int i = 1; i <= n; i++)
        {
                read(num[i]);
                MAXX = max(MAXX, num[i]);
        }
        Euler();
        //        for (int i = 1; i <= 20; i++)
        //        {
        //                cout << i << " " << leftprime[i] << endl;
        //        }
        for (int i = 1; i <= n; i++)
        {
                rans[i] = n + 1;
        }
        for (int i = 1; i <= n; i++)
        {
                cnt = num[i];
                if (cnt == 1)
                {
                        continue;
                }
                //cout<<i<<"   ";
                if (check[cnt] == 0)
                {
                        //cout << "l "<<cnt << endl;
                        lans[i] = max(fanwei[cnt], lans[i]);
                        fanwei[cnt] = i;
                        continue;
                }
                while (check[cnt])
                {
                        //cout << "l " << cnt << endl;
                        int primenow = leftprime[cnt];
                        lans[i] = max(fanwei[primenow], lans[i]);
                        fanwei[primenow] = i;
                        while (cnt % primenow == 0)
                        {
                                cnt /= primenow;
                        }
                }
                if (cnt == 1)
                {
                        continue;
                }
                else
                {
                        //cout << "l " << cnt << endl;
                        lans[i] = max(fanwei[cnt], lans[i]);
                        fanwei[cnt] = i;
                }
        }
        for (int i = 1; i <= N; i++)
        {
                fanwei[i] = n + 1;
        }
        for (int i = n; i >= 1; i--)
        {
                cnt = num[i];
                if (cnt == 1)
                {
                        continue;
                }
                //cout<<i<<"   ";
                if (check[cnt] == 0)
                {
                        //cout << "r "<<cnt << endl;
                        rans[i] = min(fanwei[cnt], rans[i]);
                        fanwei[cnt] = i;
                        continue;
                }
                while (check[cnt])
                {
                        //cout << "r "<<cnt << endl;
                        int primenow = leftprime[cnt];
                        rans[i] = min(fanwei[primenow], rans[i]);
                        fanwei[primenow] = i;
                        while (cnt % primenow == 0)
                        {
                                cnt /= primenow;
                        }
                }
                if (cnt == 1)
                {
                        continue;
                }
                else
                {
                        //                        cout << "r "<<cnt << endl;
                        //                        cout << cnt << endl;
                        rans[i] = min(fanwei[cnt], rans[i]);
                        fanwei[cnt] = i;
                }
        }
        //                for(int i=1;i<=n;i++)
        //                {
        //                        cout<<i<<" "<<lans[i]<<" "<<rans[i]<<endl;
        //                }
        flagsum = get_ans(0, 1, n);
        if (!flagsum)
        {
                cout << "impossible" << endl;
        }
        else
        {
                for (int i = 1; i <= n; i++)
                {
                        cout << father[i];
                        if (i != n)
                        {
                                cout << " ";
                        }
                }
                cout << endl;
        }
        return 0;
}
View Code

G

几何题

H

小的直接暴力 大的加给大的

I

背包DP  记录路径还需要一个二维数组

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 1e6 + 5, MAXM = 1e5 + 5;
const int MAXQ = 100010;
//int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
/*inline void addedge(int u, int v, ll c)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        cost[tot] = c;
        Head[u] = tot;
}*/
inline void read(int &v)
{
        v = 0;
        char c = 0;
        int p = 1;
        while (c < '0' || c > '9')
        {
                if (c == '-')
                {
                        p = -1;
                }
                c = getchar();
        }
        while (c >= '0' && c <= '9')
        {
                v = (v << 3) + (v << 1) + c - '0';
                c = getchar();
        }
        v *= p;
}
struct node
{
        int index;
        int w;
        int t;
} app[505];
bool cmp(node a, node b)
{
        return a.t > b.t;
}
int dp[505][10005];
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);

        int n, m;
        int d, s;
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
                scanf("%d %d", &d, &s);
                app[i].index = i;
                app[i].w = max(d, s);
                app[i].t = app[i].w - s;
        }
        sort(app + 1, app + 1 + n, cmp);
        for (int i = 0; i <= n; i++)
        {
                for (int j = 0; j <= m; j++)
                {
                        dp[i][j] = -INT_MAX;
                }
        }
        dp[0][m] = 0;
        for (int i = 1; i <= n; i++)
        {
                for (int j = 0; j <= m; j++)
                {
                        dp[i][j] = dp[i - 1][j];
                }
                for (int j = 0; j <= m; j++)
                {
                        if (dp[i - 1][j] >= 0)
                        {
                                if (j < app[i].w)
                                {
                                        continue;
                                }
                                dp[i][j - app[i].w + app[i].t] = max(dp[i - 1][j] + 1, dp[i][j - app[i].w + app[i].t]);
                        }
                }
        }
        int anser = 0;
        for (int i = 0; i <= m; i++)
        {
                anser = max(anser, dp[n][i]);
        }
        cout << anser << endl;
        return 0;
}
View Code

J

找规律题

我们可以通过打暴力程序对比发现每个2一轮一轮地模拟和一个一个地模拟得到的结果是一样的

但是直接把一个一个滚的模拟交上去会T7 需要再简化一下 

每当遇到一个二 找到它左边最近的0和右边最近的0位置分别为L与R

则这一段数列除了L+R-i这个位置变成0 其他位置都会变成1

K

概率题

猜你喜欢

转载自www.cnblogs.com/Aragaki/p/9325999.html