[log] lightOJ 刷题

数据结构

loj 1188 - Fast Queries

题意:
N <= 1e5, 1 <= ai <= 1e9
然后 m 个询问 [l, r], m <= 1e5
问你 [l, r] 中有数的种类是多少
思路:
对每一种数,只需要存他最新的位置就行了。
从1到n扫一遍,对ai先把其旧的位置删除,然后i位置加1,可以用BIT维护。同时回答每个询问。
时间复杂度: O(n+m)
这道题有个类似的:Hackerrank Coloring Tree

动态规划

loj 1073 - DNA Sequence

题意:
n个只含A,G,C,T的string。求一个长度最短的串使得给出的字符串都是其子串。相同长度的输出字典序最小的。
思路:
压位dp 注意处理一个string为另一个string的子串的情况
先dp求出最短长度
利用dp时保存的状态,标记出最优解的转移路线
然后dfs 求出字典序最小的解
dfs的时候 要同时判断长度, 因为可能沿没有标记的路线进行转移!
这一点很重要,若没有理解清楚,便难以理解为什么会wa。
下面的数据就是一个trick (对于我的代码,即 dfs 时没有判断长度的
1
4
ACGT
CCC
CGGTTTTTC
TACG

图论

loj 1108 - Instant View of Big Bang

在有向图中,求出可以到达负环的那些点。
从负环反向遍历即可。
关键是检测出所有负环,并且把上面的点标记出来。
spfa和bellman-ford都可以,我们只要标记在第n+1轮还能被松弛的点就好。(因为这些点或在负环上,或可以有负环到达
但不解的是,最开始yy的dfs找负环竟然WA了 - -

搜索

loj 1127 - Funny Knapsack

meet-in-the-middle
贴个非DFS的

int n, W;
int as[35];
typedef pair<LL, int> P;

void calc(vector<P>& v) {
    for(int i=v.size()-2; i>=0; --i)
        v[i].second += v[i+1].second;
}

void calc(map<LL, int>& xm, int s, int t) {
    map<LL, int>::reverse_iterator it;
    xm[0] = 1;
    stack<P> tmp;
    for(int i=s;i<t;++i) {
        for(it=xm.rbegin(); it!=xm.rend(); ++it)
            if ( it->first + as[i] <= W )
                tmp.push( make_pair(it->first + as[i], it->second) );
        while ( !tmp.empty() ) {
            xm[tmp.top().first] += tmp.top().second;
            tmp.pop();
        }
    }
}

int sol() {
    int k = n/2;
    map<LL, int> xm, ym;

    calc(xm, 0, k); calc(ym, k, n);

    vector<P> v1, v2;
    map<LL, int>::reverse_iterator it;
    map<LL, int> & ma = xm;
    map<LL, int> & mb = ym;
    for(it = ma.rbegin(); it != ma.rend(); ++ it) v1.push_back( *it );
    for(it = mb.rbegin(); it != mb.rend(); ++ it) v2.push_back( *it );
    calc(v2);

    int ret = 0;
    for(int i=0;i<v1.size();++i) {
        P res = make_pair(W - v1[i].first, INT_MAX);
        int pos = lower_bound(v2.begin(), v2.end(), res, greater<P>() ) - v2.begin();
        if ( pos >= v2.size() ) continue;
        ret += v1[i].second * v2[pos].second;
    }

    return ret;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in", "r", stdin);
#endif
    int t, cas = 0; scanf("%d", &t);
    while ( t -- ) {
        scanf("%d%d", &n, &W);
        rep(i, 0, n-1) scanf("%d", as+i);
        printf("Case %d: %d\n", ++cas, sol());
    }
    return 0;
}

数学类

loj 1132 - Summing up Powers

1) 类似二分法求等比数列, 二分同时保存 (length,power)这样的状态。
2) 构造矩阵递推
根据
Ckkik+Ck1kik1+...+C0ki0=(i+1)k
来构造出矩阵
http://www.cnblogs.com/jianglangcaijin/p/3443842.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值