UOJ Logo RainAir的博客

博客

正睿OI联赛停课训练day11翻车记

2018-10-29 12:52:17 By RainAir

UPD: 哥哥们怎么都给差评啊QAQ @siyuan 说他想说这句话:

Siyuan 要 AK IOI!!!

本来以为自己是300分的...结果 $\to$ T1 不判 $l==r$ $ 70 $ 分 + T2 题目玄学取模 $ 30 $ 分 + T3 错用大根堆 $ 0 $ .

最后还掉了分...

告诉我们千万不要再 自认为AK 后去做一些别的事情还有被别人瞎膜最后被奶死。

大体总结:基本全是结论题,全是坑的较为简单的(相比泡泡糖)的模拟赛 $qwq$

线段树什么的最讨厌了

发现一个长度为 $len$ 区间 $[l,r]$ 的父亲只有四种情况:$[l,r+len],[l-len,r],[l,r+len-1],[l-len-1,r]$

大力dfs即可

注意到当 $l == r$ 的时候这样做可能被艹,直接特判输出 $l$ 或 $-1$. 代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define Re register
#define LL long long
#define U unsigned
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------\n")
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
#define int long long
int T;
LL L,R,lim,ans;

void dfs(LL l,LL r){
    if(r > lim || r > ans) return;
    if(!l) {ans=r;return;}
    int len = r-l+1;
    if(len+r <= lim && l >= 2*len) dfs(l,r+len);
    if(l-len >= 0) dfs(l-len,r);
    if(r+len-1 <= lim && l >= 2*len-1) dfs(l,r+len-1);
    if(!(l-len-1) || l-len-1 >= 2*len+1) dfs(l-len-1,r);
}

inline void Solve(){
    scanf("%lld%lld%lld",&L,&R,&lim);
    ans = LLONG_MAX;
    if(L == R) {printf("%lld\n",L <= lim ? L : -1);return;}
    dfs(L,R);
    if(ans == LLONG_MAX) puts("-1");
    else printf("%lld\n",ans);
}

signed main(){
    scanf("%lld",&T);
    while(T--) Solve();
    return 0;
}

已经没有什么好害怕的了

考虑到合法的括号序列 $[l,r]$ 会对这个区间的点的贡献增加 $1$

差分一下直接搞就可以了。

注意到该题的取模十分毒瘤!加起来是不需要取模的。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define Re register
#define LL long long
#define U unsigned
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------\n")
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
#define int long long // important!!!
const int MAXN = 1000000 + 5;
const int ha = 1000000000+7;
int T,N;
char str[MAXN];
int st[MAXN],tp;
int l[MAXN],r[MAXN];
int rr[MAXN],ll[MAXN],f[MAXN];
LL ans;

inline void Solve(){
    ans = 0ll;
    scanf("%s",str + 1);
    N = strlen(str + 1);
    tp=0;CLR(l,0);CLR(r,0);CLR(ll,0);CLR(rr,0);CLR(f,0);
    FOR(i,1,N){
        if(str[i] == '(') st[++tp] = i;
        else if(tp){
            r[st[tp]] = i+1;
            l[i+1] = st[tp--];
        }
    }
    ROF(i,N+1,1) rr[l[i]] += ++rr[i];
    FOR(i,1,N+1) ll[r[i]] += --ll[i];
    FOR(i,1,N) f[i] = f[i-1] + rr[i] + ll[i];
    FOR(i,1,N) ans = (ans + i*f[i]%ha);
    printf("%lld\n",ans);
}

signed main(){
    scanf("%lld",&T);
    while(T--) Solve();
    return 0;
}

我才不是萝莉控呢

由于只能向左走,考虑动态规划。

设 $f[i][j]$ 表示走到点 $(i,j)$ 的最小花费,转移有 $f[i][j] = min(f[i-1][j+1],f[i][(j+1)/2 + \sum_{k=i+1}^n a[k])$

注意到该转移方程十分像 Huffman 树的动态规划做法的转移方程: 设 $g[i][j]$ 表示已经放置了 $i$ 个点,还需要放置 $j$ 个点的最小代价,转移有 $f[i][j] = min(f[i+1][j-1],f[i][j*2] + \sum_{k=i+1}^n val[k])$,只是过程倒过来了而已。

直接用优先队列维护一下求出序列 $a$ 的 Huffman 树的权值即可。注意 priority_queue<int> 默认是大根堆!!!不要像我这样被坑死了!!!

#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

#define Re register
#define LL long long
#define U unsigned
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------\n")
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
#define int long long //important
const int MAXN = 100000 + 5;
const int CANSIZE = 1000 + 5;

int N,x;
int a[MAXN],b[MAXN];
int f[CANSIZE][CANSIZE];
std::priority_queue<int,std::vector<int>,std::greater<int> > q;

inline void Solve(){
    scanf("%lld",&N);
    while(!q.empty()) q.pop();
    FOR(i,1,N) scanf("%lld",&x),q.push(x);
    int ans=0;
    FOR(i,1,N-1){
        int cnt=0;cnt += q.top();q.pop();
        cnt += q.top();q.pop();q.push(cnt);
        ans += cnt;
    }
    printf("%lld\n",ans);
}

signed main(){
    int T;scanf("%lld",&T);
    while(T--) Solve();
    return 0;
}

评论

siyuan
前排 Orz RainAir!
  • 2018-10-29 12:54:29
hepan
前排 Orz RainAir!
  • 2018-10-29 12:59:30
lioutao
前排 Orz RainAir和siyuan!
  • 2018-10-29 13:00:52
bearThinking
中排 Orz @RainAir@siyuan@lioutao
  • 2018-10-29 13:06:45
RainAir
Orz @siyuan @bearThinking @hepan @lioutao!!!
  • 2018-10-29 13:28:51
HandwerSTD
Orz @RainAir
  • 2018-10-29 13:36:06
tyf
楼上怎么全在fake啊,只有我是真菜!
  • 2018-10-29 13:45:08
lioutao
千古神犇@RainAir@siyuan@hepan@bearThinking ,扑通扑通跪下来!
  • 2018-10-29 13:48:31
lioutao
千古神犇@tyf 扑通扑通跪下来
  • 2018-10-29 13:49:12
zmwang
后排Orz @RainAir @siyuan @bearThinking @hepan @lioutao @tyf
  • 2018-10-29 13:59:51
hepan
楼上怎么全在fake啊,只有我是真菜!
  • 2018-10-29 14:07:08
lioutao
后排Orz @RainAir @siyuan @bearThinking @hepan @zmwang @tyf
  • 2018-10-29 15:00:34
hepan
后排Orz @RainAir @siyuan @bearThinking @zmwang @tyf @lioutao
  • 2018-10-29 15:05:42
zhengruioi
Orz....楼上的大佬
  • 2018-10-29 17:55:24
shq
Orz @RainAir
  • 2019-01-27 10:41:36