zoukankan      html  css  js  c++  java
  • LightOJ 1343

    题目链接


    题意:给定一个序列,从中选择偶数个数,满足某些性质,不改变本来的先后顺序,问有多少种选择方法。
    选出的序列 (w_1,w_2,w_3,cdots,w_{2m}),需要满足性质:

    (w_1+w_{2m} > w_2 + w_{2m-1} > cdots > w_m + w_{m+1})

    其实如果不是分类的题的话,是很难想到这样做的。

    思路:

    将所有的(w_i+w_j)处理出来。

    dp的思路: dp[i][j]表示以i为下界,以j为上界能组成的序列个数

    [dp[i][j] = sum_{i<x<y<j}dp[x][y] + 1 ]

    利用二维树状数组来快速的得到转移方程右边的求和公式。将所有的(w_i+w_j)处理成三元组(i,j,val),按照val排序,val相同按照i从小到大排,i相同按照j从大到小排,保证先处理值最小,而且区间大的(这里为了保证如果值相同的时候,统计可行序对不会把值相同的序对算进去)。

    寻找序对(i,j)的方式是统计以(i,i)为左下角,(j,j)为右上角的矩形中的数值和,每次得到答案,就更新矩形(i,j)处的值。

    类似于那个求最长上升子序列个数的题目(树状数组+DP)的思想


    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <stack>
    #include <string>
    #include <bitset>
    #include <ctype.h>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    const int INF = 0x3f3f3f3f;
    const double eps = 1e-9;
    const int N = 700 + 5;
    const LL mod = 1LL << 32;
    
    int n;
    LL c[N][N];
    inline int lowbit(int i)
    {
        return i&(-i);
    }
    void add(int x, int y, int val)
    {
        for(int i = x; i <= n; i += lowbit(i))
        {
            for(int j = y; j <= n; j += lowbit(j))
                c[i][j] = (c[i][j] + val)%mod;
        }
    }
    LL sum(int x, int y)
    {
        LL ans = 0;
        for(int i = x; i > 0; i -= lowbit(i))
        {
            for(int j = y; j > 0; j -= lowbit(j))
                ans = (c[i][j] + ans)%mod;
        }
        return ans;
    }
    
    
    struct Node
    {
        int x,y;
        LL sum;
        Node(){}
        Node(int _x, int _y, LL s)
        {
            x = _x; y = _y;
            sum = s;
        }
    };
    bool cmp(Node a, Node b)
    {
        if(a.sum == b.sum)
        {
            return a.x == b.x ? a.y>b.y : a.x<b.x;
        }
        return a.sum < b.sum;
    }
    vector<Node> tmp;
    int t, kase = 0;
    LL a[N];
    int main()
    {
        scanf("%d", &t);
        while(t--)
        {
            tmp.clear();
            scanf("%d", &n);
            memset(c, 0, sizeof(c));
            for(int i = 1; i <= n; i++)
            {
                scanf("%lld", &a[i]);
            }
            for(int i = 1; i <= n; i++)
            {
                for(int j = i+1; j <= n; j++)
                {
                    tmp.push_back(Node(i,j,(a[i]+a[j])%mod));
                }
            }
            sort(tmp.begin(), tmp.end(), cmp);
            LL res = 0;
            for(int i = 0; i < tmp.size(); i++)
            {
                int x = tmp[i].x, y = tmp[i].y;
                LL ans = (sum(y-1,y-1) - sum(x,y-1) - sum(y-1, x) + sum(x,x) + 4*mod) % mod;
                ans = (ans + 1)%mod;
                add(x,y,ans);
                res += ans;
                res %= mod;
            }
            printf("Case %d: %lld
    ", ++kase, res);
        }
        return 0;
    }
    
  • 相关阅读:
    Clipper库中文文档详解
    uboot makefile构建分析
    nvidia tk1使用记录--基本环境搭建
    学习
    es6 es7新语法
    react dva发送请求详解(转)
    antDesign表单getFieldDecorator
    react dav
    js实现截取a标签的href属性和内容
    react学习
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7471242.html
Copyright © 2011-2022 走看看