• Codeforces 960 二进制构造子序列 完全二叉树shift模拟 主席树/MAP DP


    A

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 0x3f3f3f3f
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int turn[4][2] = {{0, 1}, { 1, 0}, { 0, -1}, { -1, 0}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    int main()
    {
            string f;
            cin >> f;
            int len = f.size();
            int flag = 1;
            int numa = 0;
            int numb = 0;
            int numc = 0;
            int now = 0;
            for (int i = 0; i < len; i++)
            {
                    if (f[i] - 'a' < now)
                    {
                            flag = 0;
                            break;
                    }
                    else
                    {
                            now = max(now, f[i] - 'a');
                    }
            }
            if (!flag)
            {
                    cout << "NO" << endl;
                    return 0;
            }
            for (int i = 0; i < len; i++)
            {
                    if (f[i] == 'a')
                    {
                            numa++;
                    }
                    else if (f[i] == 'b')
                    {
                            numb++;
                    }
                    else
                    {
                            numc++;
                    }
            }
            if (numa < 1 || numb < 1)
            {
                    cout << "NO" << endl;
                    return 0;
            }
            if (numc == numa || numc == numb)
            {
                    cout << "YES" << endl;
            }
            else
            {
                    cout << "NO" << endl;
            }
    }
    View Code

    B

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 0x3f3f3f3f
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int turn[4][2] = {{0, 1}, { 1, 0}, { 0, -1}, { -1, 0}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    priority_queue<ll, vector<ll>, less<ll>> que;
    ll a[1005];
    ll b[1005];
    int main()
    {
            ll anser = 0;
            ll n, k1, k2;
            cin >> n >> k1 >> k2;
            for (int i = 1; i <= n; i++)
            {
                    scanf("%lld", &a[i]);
            }
            for (int i = 1; i <= n; i++)
            {
                    scanf("%lld", &b[i]);
                    que.push(abs(a[i] - b[i]));
                    anser += abs(a[i] - b[i]) * abs(a[i] - b[i]);
            }
            int cur = k1 + k2;
            while (cur)
            {
                    ll now = que.top();
                    que.pop();
                    if (now == 0)
                    {
                            cur--;
                            que.push(1);
                            anser += 1;
                    }
                    else
                    {
                            cur--;
                            que.push(now - 1);
                            anser -= 1LL * now * now;
                            anser += 1LL * (now - 1) * (now - 1);
                    }
            }
            cout << anser << endl;
    }
    View Code

    C

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 0x3f3f3f3f
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int turn[4][2] = {{0, 1}, { 1, 0}, { 0, -1}, { -1, 0}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    priority_queue<ll, vector<ll>, less<ll>> que;
    vector<ll> ans;
    int main()
    {
            //freopen("out.txt","w",stdout);
            ll x, d;
            cin >> x >> d;
            //        if(x<=10000)
            //        {
            //                for(ll i=1;x;i+=d+1)
            //                {
            //                        cout<<i<<" ";
            //                        x--;
            //                }
            //                return 0;
            //        }
            ll cur = 1;
            if (x == 1)
            {
                    cout << 1 << endl;
                    cout << 1 << endl;
                    return 0;
            }
            if (x & 1)
            {
                    ans.push_back(1e17 - 1);
                    x -= 1;
            }
            for (ll i = 0; i <= 32; i++)
            {
                    if ((1LL << i)&x)
                    {
                            que.push(i);
                    }
            }
            while (!que.empty())
            {
                    ll number = que.top();
                    que.pop();
                    for (ll i = 1; i <= number; i++)
                    {
                            ans.push_back(cur);
                    }
                    cur += d;
                    ans.push_back(cur);
                    cur += d;
            }
            cout << ans.size() << endl;
            for (ll ch : ans)
            {
                    cout << ch << " ";
            }
    }
    View Code

    D

    给你一个完全二叉树有三种操作

    1.把值为X的节点所在当前层 移动K次

    2.把值为X的节点所在当前层 移动K次 子树也跟着移动

    3.询问你值为X所在结点到根节点路径上节点的值

    shift[i]表示第i层移动的次数

    第二个操作很好处理 第三个操作就是在第二个操作上pushdown 下一层移动的次数是上一层的两倍

    (记得取模操作)

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 0x3f3f3f3f
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int turn[4][2] = {{0, 1}, { 1, 0}, { 0, -1}, { -1, 0}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    int Q;
    int T;
    ll level;
    ll X, K;
    ll lenth, position;
    ll shift[70];
    void update(ll x, ll K)
    {
            shift[x] += K;
            shift[x] %= (1LL << (x - 1));
    }
    void pushdown(ll x, ll K)
    {
            shift[x] += K;
            shift[x] %= (1LL << (x - 1));
            if (x + 1 < 61)
            {
                    K = (K << 1);
                    pushdown(x + 1, K);
            }
    }
    ll getpos(ll level, ll x)
    {
            ll l = 1LL << (level - 1);
            ll r = (1LL << level) - 1;
            ll now = x + shift[level];
            if (l <= now && now <= r)
            {
                    return now;
            }
            if (now < l)
            {
                    ll cha = l - now - 1;
                    return r - cha;
            }
            else
            {
                    ll cha = now - r - 1;
                    return l + cha;
            }
    }
    void print(ll level, ll pos)
    {
            if (level == 1)
            {
                    cout << 1;
                    return ;
            }
            ll now = pos - shift[level];
            ll l = 1LL << (level - 1);
            ll r = (1LL << level) - 1;
            if (l <= now && now <= r)
            {
                    cout << now << " ";
                    print(level - 1, pos / 2);
                    return;
            }
            if (now < l)
            {
                    ll cha = l - now - 1;
                    cout << r - cha << " ";
            }
            else
            {
                    ll cha = now - r - 1;
                    cout << l + cha << " ";
            }
            print(level - 1, pos / 2);
            return ;
    }
    int main()
    {
            //freopen("out.txt","w",stdout);
            cin >> Q;
            while (Q--)
            {
                    int T;
                    scanf("%d %lld", &T, &X);
                    for (ll i = 61; i >= 1; i--)
                    {
                            if ((1LL << (i - 1))&X)
                            {
                                    if (((1LL << i)&X) == 0)
                                    {
                                            level = i;
                                            break;
                                    }
    
                            }
                    }
                    //cout<<level<<" ";
                    if (T == 1)
                    {
                            scanf("%lld", &K);
                            if (X == 1)
                            {
                                    continue;
                            }
                            K %= 1LL << (level - 1);
                            update(level, K);
                    }
                    else if (T == 2)
                    {
                            scanf("%lld", &K);
                            if (X == 1)
                            {
                                    continue;
                            }
                            K %= 1LL << (level - 1);
                            pushdown(level, K);
                    }
                    else
                    {
                            if (X == 1)
                            {
                                    cout << 1 << endl;
                                    continue;
                            }
                            cout << X << " ";
                            position = getpos(level, X);
                            //cout << position;
                            print(level - 1, position / 2);
                            cout << endl;
                    }
            }
    }
    View Code

    E

    F

    先来做F的简化版

    http://codeforces.com/contest/459/problem/E

    求有向图的最长严格递增路径

    dp[i]表示以第i条边为结尾的最长路径 g[i]表示以i结点为结尾的最长路径

    所以dp[i]=dp[edge[i].from]+1即以第i条边结尾的答案是以该边from结尾的最长路径长度+其本身

    首先排序 相同大小的边之间是不会相连的

    而如果每遍历一条边就g[edge[i].to]=max(g[edge[i].to],dp[i])的话 如果edge[i+1].from=edge[i].to 就变成这两条边相连了所以相同值的边要分处理

    复杂度NLOGN

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define MAX 300007
    using namespace std;
    int n, m;
    int dp[MAX], g[MAX];
    struct Edge
    {
            int u, v, w;
            bool operator < ( const Edge& a ) const
            {
                    return w < a.w;
            }
    } e[MAX];
    int main ( )
    {
            while ( ~scanf ( "%d%d" , &n , &m ) )
            {
                    for ( int i = 0 ; i < m ; i++ )
                    {
                            scanf ( "%d%d%d" , &e[i].u , &e[i].v , &e[i].w );
                    }
                    sort ( e , e + m );// 排序
                    int t = 0;
                    e[m].w = -1;//使得最后一组边也能更新
                    int ans = 0; //答案
                    for ( int i = 0 ; i < m ; i++ ) //从小到大枚举
                    {
                            int v = e[i].v;
                            int u = e[i].u;
                            int w = e[i].w;
                            dp[i] = g[e[i].u] + 1; //以第i条边结尾的答案是以e[i].from节点为结尾的最长路径+它本身
                            if ( e[i].w != e[i + 1].w )
                            {
                                    for ( int j = t ; j <= i ; j++ ) //处理相同边 
                                    {
                                            g[e[j].v] = max ( g[e[j].v] , dp[j] );//更新e[i].to的答案 以便处理下一组边
                                    }
                                    t = i + 1;//重置相同边的起点
                            }
                            ans = max ( ans , dp[i] );
                    }
                    printf ( "%d
    " , ans );
            }
    }
    View Code

    现在来做F

    如果用上面的方法来做 不能保证下标不能有逆序对这个条件

    如果去掉edge[i].from=edge[j].to这个条件的话 这道题就变成一道裸的LIS

    如果用来DP的话 普通的dp[i][j]数组表示以i为结尾的权重最大为j的最长递增路径长度 因为i和j都是1e5的会炸

    但是用MAP来存的话 因为每个dp[i]表示的都是一个树状数组 每次插入和询问都是LOGN的 所以最多只会涉及到NLOGN个节点 可以接受

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 0x3f3f3f3f
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int turn[4][2] = {{0, 1}, { 1, 0}, { 0, -1}, { -1, 0}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    const int N = 1e5 + 5;
    map<int, int> bits[N];
    int query(int u, int x)
    {
            int ans = 0;
            while (x)
            {
                    ans = max(ans, bits[u][x]);
                    x -= x & -x;
            }
            return ans;
    }
    void update(int u, int x, int v)
    {
            while (x < N)
            {
                    bits[u][x] = max(bits[u][x], v);
                    x += x & -x;
            }
    }
    int main()
    {
            int n, m, u, v, w;
            int anser = 0;
            int cur;
            scanf("%d%d", &n, &m);
            for (int i = 0; i < m; i++)
            {
                    scanf("%d%d%d", &u, &v, &w);
                    w++;
                    cur = query(u, w - 1) + 1;
                    update(v, w, cur);
                    anser = max(anser, cur);
            }
            printf("%d
    ", anser);
            return 0;
    }
    View Code

    用主席树来做的话 其实和MAP DP递推是同理的 只建立需要的节点 其他节点忽略

    #include<cstdio>
    #include<algorithm>
    #define lowbit(x) (x&-x)
    using namespace std;
    const int maxn=100010;
    int n,m,f[maxn],rt[maxn],sz;
    struct tree{int l,r,mx;}t[maxn*20];
    void insert(int& k,int l,int r,int x,int y){
        if(!k)k=++sz;t[k].mx=max(t[k].mx,y);
        if(l==r)return;
        int mid=(l+r)>>1;
        if(x<=mid)insert(t[k].l,l,mid,x,y);
        else insert(t[k].r,mid+1,r,x,y);
    }
    int query(int k,int l,int r,int x){
        if(l==r)return t[k].mx;
        int mid=(l+r)>>1;
        if(x<=mid)return query(t[k].l,l,mid,x);
        else return max(t[t[k].l].mx,query(t[k].r,mid+1,r,x));
    }
    int main(){
        scanf("%d%d",&n,&m);
        int ans=0;
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            f[i]=query(rt[u],1,100000,w-1)+1;
            insert(rt[v],1,100000,w,f[i]);
            ans=max(ans,f[i]);
        }
        printf("%d",ans);
        return 0;
    
    }
    View Code
  • 相关阅读:
    [NOIp2017] 列队
    [CQOI2009] 中位数
    [洛谷P1419] 寻找段落
    [HNOI2001] 产品加工
    [洛谷P1842] 奶牛玩杂技
    [SCOI2006] 数字立方体
    [LOJ10121] 与众不同
    [USACO10MAR] 伟大的奶牛聚集
    [HAOI2010] 软件安装
    [洛谷P1357] 花园
  • 原文地址:https://www.cnblogs.com/Aragaki/p/8760397.html
Copyright © 2020-2023  润新知