uestc summer training #2

A

增广

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1000000 + 10;
vector<int> g[MAXN];
int a[MAXN], b[MAXN], sz[MAXN], cnt[MAXN];
bool mg[MAXN], vis[MAXN];
int n, m;
bool dfs(int u, int f = -1)
{
        if (g[u].empty())  //如果当前数没有位置是成对的(a[i+1]=a[i]+1)当然不可能缝
        {
                return false;
        }
        //第一种情况 
        for (auto &p : g[u])  //枚举当前数每个成对的位置
                if (p != f)
                {
                        if (!vis[p + 1] || cnt[u + 1] == 1) //如果当前这对后面的位置没有被缝并且后面的数数量为1
                        {
                                mg[p] = vis[p] = vis[p + 1] = 1;  //缝起来 返回true
                                if (f != -1)
                                {
                                        mg[f] = 0;
                                }
                                return true;
                        }
                }
        for (auto &p : g[u])
                if (p != f)
                {
                        if (dfs(u + 1, p + 1))
                        {
                                mg[p] = vis[p] = vis[p + 1] = 1;
                                if (f != -1)
                                {
                                        mg[f] = 0;
                                }
                                return true;
                        }
                }
        return false;
}
int main()
{
        scanf("%d", &n);
        m = 0; //m是当前数组的数量
        for (int i = 0, p(-1); i < n; ++ i)
        {
                int x;
                scanf("%d", &x);
                if (x == p)  //p是上一个加入的数
                {
                        sz[m - 1] ++; //如果现在加入的和上一个相同就给上一个sz++
                }
                else            //不同的话 加入当前数更新p
                {
                        p = x;
                        a[m] = x;
                        sz[m ++] = 1;
                }
        }
        n = m;
        for (int i = 0; i < n; i++)
        {
                b[i] = a[i];
        }
        sort(b, b + n);
        for (int i = m = 0; i < n; i++)  //初始化m进行离散化操作
                if (i == 0 || b[i] > b[m - 1])
                {
                        b[m++] = b[i];
                }
        for (int i = 0; i < n; ++ i)  //离散化
        {
                a[i] = lower_bound(b, b + m, a[i]) - b;
                cnt[a[i]] ++;  //计数 计算每种数的数量
        }
        //        for (int i = 0; i < n; i++)
        //        {
        //                cout << a[i] << " ";
        //        }
        //        cout << endl;
        for (int i = 0; i + 1 < n; ++ i)
        {
                if (a[i] + 1 == a[i + 1]) //如果后一个是前一个+1就建一条有向边
                {
                        g[a[i]].push_back(i);  //记录每一对可以缝的位置前面的哪个
                }
        }
        int ret = n - 1; //答案(缩点之后缝之前的答案 这里claris姐姐写错了 应该是n-1)
        for (int i = m - 1; i >= 0; -- i) //从大到小尝试是否可以缝当前的数
        {
                if (dfs(i))  //如果返回true即可以缝的话 答案减少一个
                {
                        -- ret; //对于每一种数 最多只能缝一次 所以最多-1
                }
        }
        printf("%d", ret);
}
View Code

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 pair<int, int> PINT;
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, INF = 1e9;
//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 first, second, index;
} bag[505];
bool cmp(node a, node b)
{
        return (a.first - a.second) > (b.first - b.second);
}
int dp[505][10005];
int print[505][10005];
PINT before[505][10005];
stack<int> anser;
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);

        int n, c;
        scanf("%d %d", &n, &c);
        for (int i = 1; i <= n; i++)
        {
                scanf("%d %d", &bag[i].first, &bag[i].second);
                bag[i].index = i;
        }
        sort(bag + 1, bag + 1 + n, cmp);
        int ans = 0;
        for (int i = 1; i <= n; i++)
                for (int j = 0; j <= c; j++)
                {
                        dp[i][j] = -INF;
                }
        dp[0][0] = 0;
        PINT ed = make_pair(0, 0);
        for (int i = 1; i <= n; i++)
        {
                for (int j = 0; j <= c; j++)
                {
                        if (dp[i - 1][j] > dp[i][j])
                        {
                                dp[i][j] = dp[i - 1][j];
                                before[i][j] = make_pair(i - 1, j);
                                print[i][j] = print[i - 1][j];
                        }
                }
                for (int j = 1; j <= c; j++)
                {
                        if (j >= bag[i].second && j + bag[i].first - bag[i].second <= c)
                        {
                                if (dp[i - 1][j - bag[i].second] != -INF)
                                {
                                        if (dp[i][j] < dp[i - 1][j - bag[i].second] + 1)
                                        {
                                                dp[i][j] = dp[i - 1][j - bag[i].second] + 1;
                                                print[i][j] = bag[i].index;
                                                before[i][j] = make_pair(i - 1, j - bag[i].second);
                                                if (dp[i][j] > ans)
                                                {
                                                        ans = dp[i][j];
                                                        ed = make_pair(i, j);
                                                }
                                        }
                                }
                        }
                }
        }
        int printnow;
        cout << ans << endl;
        for (; ed.first; ed = before[ed.first][ed.second])
        {
                if (printnow != print[ed.first][ed.second] && print[ed.first][ed.second] != 0)
                {
                        anser.push(print[ed.first][ed.second]);
                }
                printnow = print[ed.first][ed.second];
        }
        while (!anser.empty())
        {
                cout << anser.top() << " ";
                anser.pop();
        }
        return 0;
}
View Code

J

找规律题

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

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

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

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

K

概率题

原文地址:https://www.cnblogs.com/Aragaki/p/9325999.html