In mathematics you don't understand things, you just get used to them.

标签 data structures 下的文章

我是傻逼。

「CF 1539A」Contest Start

Link.

答案是 $\sum_{i=1}^{n-1}\min\{i,\lfloor\frac{t}{x}\rfloor\}$,等差数列求和优化。

#include<bits/stdc++.h>
#define con(typ) const typ
typedef long long ll;
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static int s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
int main(){
    int T;
    ll n,x,t;
    for(sf(T);T;--T){
        sf(n),sf(x),sf(t);
        ll ans=0,d=t/x;
        --n;
        if(n>=d)ans=(n-d)*d+d*(d+1)/2;
        else ans=n*(n+1)/2;
        pf(ans);
    }
    return 0;
}

「CF 1539B」Love Song

Link.

暴力。

#include<bits/stdc++.h>
#define con(typ) const typ
typedef long long ll;
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static int s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
int cap[100010][26],n,q;
char ch[100010];
int main(){
    sf(n),sf(q);
    scanf("%s",ch+1);
    for(int i=1;i<=n;++i){
        memcpy(cap[i],cap[i-1],sizeof(int)*26);
        cap[i][ch[i]-'a']++;
    }
    for(int l,r;q;--q){
        sf(l),sf(r);
        ll ans=0;
        for(int i=0;i<26;++i)ans+=(i+1)*(cap[r][i]-cap[l-1][i]);
        pf(ans);
    }
    return 0;
}

「CF 1539C」Stable Groups

Link.

贪心。

对原序列差分,把差分值拿出来排序后把前几个填了。正确性显然。

#include<bits/stdc++.h>
#define con(typ) const typ
typedef long long ll;
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static int s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
int n;
ll a[200010],k,x,df[200010];
int main(){
    sf(n);sf(k);sf(x);for(int i=1;i<=n;++i)sf(a[i]);
    sort(a+1,a+n+1);
    for(int i=2;i<=n;++i)df[i]=a[i]-a[i-1];
    vector<ll> ald;
    for(int i=2;i<=n;++i){
        if(df[i]>x)ald.emplace_back(df[i]);
    }
    sort(all(ald));
    int del=0;
    for(int i=0;i<int(ald.size());++i){
        ll w=ald[i];
        if(w%x==0){
            if(k>=w/x-1)k-=w/x-1,++del;
            else break;
        }
        else{
            if(k>=w/x)k-=w/x,++del;
            else break;
        }
    }
    pf(int(ald.size())-del+1);
    return 0;
}

「CF 1539D」PriceFixed

Link.

以 $b$ 为关键字排序。

首先考虑把第一个元素「激活」,即填满 $b_{1}$ 个商品。

然后后面的元素有两种决策:

  1. 使用前面已经「激活」的商品来「激活」该商品后买完;
  2. 直接买 $a_{i}$ 个,注意分 $a_{i},b_{i}$ 大小讨论。

两种决策会使总买入商品数不一致,对后面有影响(?)。

现在考场上那个傻逼在想 DP。

但是注意到这样搞的代价是没有差别的,$2-1=1$ 抵了。

那么就一定存在一种最优方案使得每种产品买恰好 $a_{i}$ 个,搞两个指针扫一下就行了。

#include<bits/stdc++.h>
#define con(typ) const typ
typedef long long ll;
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static int s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
struct st{ll a,b;}a[100010];
int n;
int main(){
    sf(n);for(int i=1;i<=n;++i)sf(a[i].a),sf(a[i].b);
    sort(a+1,a+n+1,[](st x,st y){return x.b<y.b || (x.b==y.b && x.a<y.a);});
    ll nw=0,ans=0;
    for(int i=1,j=n;i<=j;){
        if(nw>=a[i].b){
            ans+=a[i].a;
            nw+=a[i].a;
            ++i;
        }
        else{
            if(a[j].a+nw>=a[i].b){
                ll temp=a[i].b-nw;
                ans+=2*temp;
                nw+=temp;
                a[j].a-=temp;
            }
            else{
                ans+=a[j].a*2;
                nw+=a[j].a;
                --j;
            }
        }
    }
    pf(ans);
    return 0;
}

「CF 1539E」Game with Cards

Link.

gap 略大。搞不动先咕着。

「CF 1539F」Strange Array

Link.

假的,懒得写了,具体看 Rainybunny 的评论吧。

$\ \ \ \ $F:发现对于某个 $a_{i}$,已知包含它的某个区间中,$\le a_{i}$ 与 $>a_{i}$ 的数的数量差就能得到它的特征值。不妨令“大于等于”为 $+1$,“小于”为 $-1$,线段树维护区间最大前缀和与最大后缀和,升序扫描 $a$ 值就能更新答案。$+1,-1$ 反过来再做一遍,最后是 $\mathcal O(n\log_{2}n)$ 的。
$\ \ \ \ $赛后瞬间补题的原因大概是细节有点多√

#include<bits/stdc++.h>
#define con(typ) const typ
typedef long long ll;
#define all(x) (x).begin(),(x).end()
using namespace std;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static int s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
template<typename T,typename... Tt>void sf(T &x,Tt&... aa){sf(x),sf(aa...);}
int n,a[200010],stp,Segres;
vector<int> ps[200010];
struct node{int p,s,sm;node(int a=0,int b=0,int c=0){p=a;s=b;sm=c;}};
struct Segtree{
    const int n;
    vector<node> ns;
    Segtree(int n,int fl):n(n),ns(n*4+5){give(1,n,1,fl);}
    node mrg(node a,node b){
        node c;
        c.p=max(a.p,a.sm+b.p);
        c.s=max(b.s,b.sm+a.s);
        c.sm=a.sm+b.sm;
        return c;
    }
    void give(int l,int r,int p,int v){
        if(r-l==0){ns[p]=node(max(v,0),max(v,0),v);return;}
        int m=(l+r)/2;
        give(l,m,p*2,v),give(m+1,r,p*2+1,v);
        ns[p]=mrg(ns[p*2],ns[p*2+1]);
    }
    void ins(int l,int r,int p,int x,int v){
        if(r-l==0){ns[p]=node(max(v,0),max(v,0),v);return;}
        int m=(l+r)/2;
        if(m>=x)ins(l,m,p*2,x,v);
        else ins(m+1,r,p*2+1,x,v);
        ns[p]=mrg(ns[p*2],ns[p*2+1]);
    }
    void qpre(int l,int r,int p,int x){
        if(l>=x){stp=max(stp,Segres+ns[p].p);Segres+=ns[p].sm;return;}
        int m=(l+r)/2;
        if(m>=x)qpre(l,m,p*2,x);qpre(m+1,r,p*2+1,x);
    }
    void qsuf(int l,int r,int p,int x){
        if(r<=x){stp=max(stp,Segres+ns[p].s);Segres+=ns[p].sm;return;}
        int m=(l+r)/2;
        if(m<x)qsuf(m+1,r,p*2+1,x);qsuf(l,m,p*2,x);
    }
    void ins(int x,int y){ins(1,n,1,x,y);}
    int qpre(int x){Segres=stp=0;qpre(1,n,1,x);return stp;}
    int qsuf(int x){Segres=stp=0;qsuf(1,n,1,x);return stp;}
};
int main(){
    sf(n);for(int i=1;i<=n;++i)sf(a[i]),ps[a[i]].emplace_back(i);
    int value=1;
    vector<int> ans(n);
    for(int value=1;value>-2;value-=2){
        Segtree t(n,value);
        for(int i=1;i<=n;++i){
            if(value==-1)for(int x:ps[i])t.ins(x,-value);
            for(int x:ps[i]){
                int r0,r1;
                r1=t.qpre(x);
                r0=t.qsuf(x);
                if((r0+r1-1)&1)ans[x-1]=max(ans[x-1],(r0+r1-1)/2);
                else{
                    if(value==1)ans[x-1]=max(ans[x-1],(r0+r1-1)/2);
                    else ans[x-1]=max(ans[x-1],(r0+r1-2)/2);
                }
            }
            if(value==1)for(int x:ps[i])t.ins(x,-value);
        }
    }
    for(int x:ans)pf(x,' ');
    return 0;
}

「CF 1514A」Perfectly Imperfect Array

Link.

就看序列中是否存在不为平方数的元素即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static T s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
ll T,n,x;
bool check(ll x)
{
    for(ll i=1;i*i<=x;++i)    if(i*i==x)    return true;
    return false;
}
int main()
{
    for(sf(T);T;--T)
    {
        sf(n);
        bool fl=0;
        for(int i=1;i<=n;++i)
        {
            sf(x);
            if(!check(x))    fl=1;
        }
        if(fl)    puts("YES");
        else    puts("NO");
    }
    return 0;
}

「CF 1514B」AND 0, Sum Big

Link.

和最大的情况就是每个数都只有一个 $0$(二进制下),于是答案就是 $n^{k}$。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static T s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
const int MOD=1e9+7;
int main()
{
    int T,n,k;
    for(sf(T);T;--T)
    {
        sf(n),sf(k);
        ll ans=1;
        for(int i=1;i<=k;++i)    ans*=n,ans%=MOD;
        pf(ans);
    }
    return 0;
}

「CF 1514C」Product 1 Modulo N

Link.

把所有与 $n$ 互质的数拉出来,如果 product 不满足要求,就把最后一个剔除。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static T s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
int n;
ll op(ll x,ll y){return x*y%n;}
int main()
{
    sf(n);
    std::vector<ll> ans;
    for(int i=1;i<=n;++i)    if(__gcd(i,n)==1)    ans.emplace_back(i);
    if(accumulate(ans.begin(),ans.end(),1,op)!=1)    ans.pop_back();
    pf(ans.size());
    for(int i:ans)    pf(i,' ');
    return 0;
}

「CF 1514D」Cut and Stick

Link.

答案是 $\max\{1,2x-l\}$,$l$ 为区间长度,$x$ 为众数出现次数。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

const int MAXN = 5e5 + 5, MAXM = 720 + 5;

char buf[1 << 21], *p1 = buf, *p2 = buf;
#define getchar( ) ( p1 == p2 && ( p2 = ( p1 = buf ) + fread( buf, 1, 1 << 21, stdin ), p1 == p2 ) ? EOF : *p1 ++ )

template<typename _T>
void read( _T &x ){
    x = 0; char c = getchar( ); _T f = 1;
    while( c < '0' || c > '9' ){ if( c == '-' )    f = -1; c = getchar( ); }
    while( c >= '0' && c <= '9' ){ x = ( x << 3 ) + ( x << 1 ) + ( c & 15 ); c = getchar( ); }
    x *= f;
}

template<typename _T>
void write( _T x ){
    if( x < 0 ){ putchar( '-' ); x = -x; }
    if( x > 9 ){ write( x / 10 ); }
    putchar( x % 10 + '0' );
}

template<typename _T>
void swapp( _T &one, _T &another ){ int temp = one; one = another; another = temp; }

template<typename _T>
_T MIN( _T one, _T another ){ return one > another ? another : one; }

template<typename _T>
_T MAX( _T one, _T another ){ return one > another ? one : another; }

int N, M;
int cube, each, kase, isa[MAXN], cnt[MAXN], pos[MAXN], vis[MAXN], bel[MAXN];
int lps[MAXM], rps[MAXM], App[MAXM][MAXM];
vector<int> disc, fur[MAXN];

int getID( int x ){ return lower_bound( disc.begin( ), disc.end( ), x ) - disc.begin( ) + 1; }

void build( ){
    memset( cnt, 0, sizeof( cnt ) );
    for( int i = 1; i <= cube; ++ i ){
        kase ++;
        for( int j = i; j <= cube; ++ j ){
            App[i][j] = App[i][j - 1];
            for( int k = lps[j]; k <= rps[j]; ++ k ){
                if( vis[isa[k]] != kase )    cnt[isa[k]] = 0;
                cnt[isa[k]] ++; App[i][j] = MAX( App[i][j], cnt[isa[k]] );
                vis[isa[k]] = kase;
            }
        }
    }
    memset( cnt, 0, sizeof( cnt ) );
}

int query( int opl, int opr ){
    if( bel[opl] == bel[opr] ){
        int res = 0; kase ++;
        for( int i = opl; i <= opr; ++ i ){
            if( vis[isa[i]] != kase )    cnt[isa[i]] = 0;
            cnt[isa[i]] ++; res = MAX( res, cnt[isa[i]] );
            vis[isa[i]] = kase;
        }
        return res;
    }
    int res = 0;
    res = App[bel[opl] + 1][bel[opr] - 1];
    for( int i = opl; i <= rps[bel[opl]]; ++ i ){
        int lim = fur[isa[i]].size( ) - 1;
        while( pos[i] + res <= lim && fur[isa[i]][pos[i] + res] <= opr )    res ++;
    }
    for( int i = lps[bel[opr]]; i <= opr; ++ i ){
        while( pos[i] - res >= 0 && fur[isa[i]][pos[i] - res] >= opl )    res ++;
    }
    return res;
}

signed main( ){
    read( N ); read( M ); each = 720; cube = ( N - 1 ) / each + 1;
    for( int i = 1; i <= N; ++ i ){ read( isa[i] ); disc.push_back( isa[i] ); }
    sort( disc.begin( ), disc.end( ) );
    disc.erase( unique( disc.begin( ), disc.end( ) ), disc.end( ) );
    for( int i = 1; i <= N; ++ i ){
        isa[i] = getID( isa[i] );
        fur[isa[i]].push_back( i );
        pos[i] = fur[isa[i]].size( ) - 1;
    }
    for( int i = 1; i <= cube; ++ i ){
        lps[i] = rps[i - 1] + 1; rps[i] = rps[i - 1] + each;
        if( i == cube )    rps[i] = N;
        for( int j = lps[i]; j <= rps[i]; ++ j )    bel[j] = i;
    }
    build( );
    int opl, opr;
    while( M -- > 0 ){
        read( opl ); read( opr );
        write( max( 1, 2 * query( opl, opr ) - ( opr - opl + 1 ) ) );
        putchar( '\n' );
    }
    return 0;
}

「CF 1514E」Baby Ehab's Hyper Apartment

Link.

// Oops, something went wrong.

「CF 1525A」Potion-making

Link.

显然。

#include<bits/stdc++.h>
typedef long long ll;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static T s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
int main()
{
    int T,k;
    sf(T);
    while(T-->0)
    {
        sf(k);
        int p1=k,p2=100-k,x=gcd(p1,p2);
        p1/=x;
        p2/=x;
        pf(p1+p2);
    }
    return 0;
}

「CF 1525B」Permutation Sort

Link.

注意到答案只有 $0/1/2/3$,分类讨论即可。

吃了三发罚时

#include<bits/stdc++.h>
typedef long long ll;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static T s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
int T,n,a[60];
int main()
{
    for(sf(T);T;--T)
    {
        sf(n);
        for(int i=1;i<=n;++i)    sf(a[i]);
        int flag=1;
        for(int i=2;i<=n;++i)
        {
            if(a[i]!=a[i-1]+1)
            {
                flag=0;
                break;
            }
        }
        if(!flag)
        {
            if(a[1]==n && a[n]==1)    puts("3");
            else if(a[n]==n || a[1]==1)    puts("1");
            else    puts("2");
        }
        else    puts("0");
    }
    return 0;
}

「CF 1525C」Robot Collisions

Link.

显然我不会。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mp make_pair
template<typename T>void sf(T &x) {
    x = 0;
    T f = 0;
    char c = getchar();

    for (; c < '0' || c > '9'; c = getchar())
        if (c == '-')
            f = 1;

    for (; c >= '0' && c <= '9'; c = getchar())
        x = (x << 3) + (x << 1) + (c^'0');

    if (f)
        x = -x;
}
template<typename T>void pf(T x, char l = '\n') {
    static T s[100], t;

    if (x < 0)
        putchar('-'), x = -x;

    do
        s[++t] = x % 10, x /= 10;

    while (x)
        ;

    while (t)
        putchar(s[t--]^'0');

    putchar(l);
}
struct st {
    int a, b, id;
} Sts[300005], Uji[300005], Qql[300005];
bool cmp(st A, st B) {
    return A.a < B.a;
}
int reait[300005];
int n, m;
int U(int x, int y) {
    int res = 0;

    if (Sts[x].a < Sts[y].a) {
        if (Sts[x].b == 0)
            res += Sts[x].a, Sts[x].a = 0;

        if (Sts[y].b == 1)
            res += (m - Sts[y].a), Sts[y].a = m;

        return (res + abs(Sts[x].a - Sts[y].a)) / 2;
    } else {
        if (Sts[x].b == 1)
            res += (m - Sts[x].a), Sts[x].a = m;

        if (Sts[y].b == 0)
            res += Sts[y].a, Sts[y].a = 0;

        return (res + abs(Sts[x].a - Sts[y].a)) / 2;
    }
}
signed main() {
    int T;
    sf(T);

    while (T--) {
        sf(n), sf(m);

        for (int i = 1; i <= n; i++)
            reait[i] = -1;

        int rks = 0, tss = 0;

        for (int i = 1; i <= n; i++) {
            sf(Sts[i].a);
            Sts[i].id = i;
        }

        for (int i = 1; i <= n; i++) {
            char res = getchar();

            while (res != 'L' && res != 'R')
                res = getchar();

            Sts[i].b = res == 'R';
        }

        for (int i = 1; i <= n; i++) {
            if (Sts[i].a & 1)
                Qql[++tss] = Sts[i];
            else
                Uji[++rks] = Sts[i];
        }

        sort(Uji + 1, Uji + rks + 1, cmp);
        sort(Qql + 1, Qql + tss + 1, cmp);
        stack <int> Q;
        Q.push(1);

        for (int i = 2; i <= rks; i++) {
            if (Uji[i].b == 0 && !Q.empty()) {
                int u = Q.top();
                Q.pop();
                reait[Uji[i].id] = reait[Uji[u].id] = U(Uji[i].id, Uji[u].id);
            } else
                Q.push(i);
        }

        while (!Q.empty()) {
            int u = Q.top();
            Q.pop();

            if (!Q.empty()) {
                int v = Q.top();
                Q.pop();
                reait[Uji[u].id] = reait[Uji[v].id] = U(Uji[u].id, Uji[v].id);
            }
        }

        Q.push(1);

        for (int i = 2; i <= tss; i++) {
            if (Qql[i].b == 0 && !Q.empty()) {
                int u = Q.top();
                Q.pop();
                reait[Qql[i].id] = reait[Qql[u].id] = U(Qql[i].id, Qql[u].id);
            } else
                Q.push(i);
        }

        while (!Q.empty()) {
            int u = Q.top();
            Q.pop();

            if (!Q.empty()) {
                int v = Q.top();
                Q.pop();
                reait[Qql[u].id] = reait[Qql[v].id] = U(Qql[u].id, Qql[v].id);
            }
        }

        for (int i = 1; i <= n; i++)
            printf("%lld ", reait[i]);

        printf("\n");
    }

    return 0;
}

「CF 1525D」Armchairs

Link.

设 $f(i,j)$ 表示考虑把第 $j$ 个人放进前 $i$ 个座位里的方案,转移。

多久没写 DP 了啊,这种水平的 DP 都写漏一堆东西。

#include<bits/stdc++.h>
typedef long long ll;
template<typename T>void sf(T &x){x=0;T f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;for(;c>='0'&&c<='9';c=getchar())x=(x<<3)+(x<<1)+(c^'0');if(f)x=-x;}
template<typename T>void pf(T x,char l='\n'){static T s[100],t;if(x<0)putchar('-'),x=-x;do s[++t]=x%10,x/=10;while(x);while(t)putchar(s[t--]^'0');putchar(l);}
int n,a[5010],fr[5010],t0,oc[5010],t1,op[5010];
ll dp[5010][5010],ans=std::numeric_limits<ll>::max();
inline int fs(int x){return x<0?-x:x;}
int main()
{
    sf(n);
    for(int i=1;i<=n;++i)
    {
        sf(a[i]);
        if(a[i])    oc[++t1]=i;
        else    fr[++t0]=i;
    }
    for(int i=1;i<=t1;++i)    for(int j=0;j<=n;++j)    dp[i][j]=1e18;
    for(int i=1;i<=t1;++i)    for(int j=1;j<=n;++j) {
        dp[i][j]=dp[i][j-1];
        if(!a[j])    dp[i][j]=std::min(dp[i][j],dp[i-1][j-1]+fs(oc[i]-j));
    }
    pf(dp[t1][n]);
    return 0;
}

「CF 1525E」Assimilation IV

Link.

// Oops, something went wrong.

「CF 1525F」Goblins And Gnomes

Link.

// Oops, something went wrong.

Description

Link.

一共 $n$ 天,每天可以卖出或者买入两种股票 $A$ 和 $B$。这两种股票在第 $i$ 天的价值为 $A_i$ 和 $B_i$。

每天可以花所有的现金买入股票,这些股票中 $A$ 股与 $B$ 股的数量比为 $rate_i$。每天也可以把所有的股票以当天的价值卖出,获得现金。已知接下来 $n$ 天的 $A_i,B_i,rate_i$,求出 $n$ 天后能够获得的最大价值。

Solution

设 $f(i)$ 为第 $i$ 天的最大钱数,$g_{1}(i)$ 为 A 券的第 $i$ 天能换的数量,$g_{2}(i)$ 则为 B 券。

转移可以解方程得:

$$ f(i)=\max\{f(i-1),a(i)g_{1}(j),b(i)g_{2}(j)\},j\in[1,i) \\ g_{1}(i)\frac{f(i)rate(i)}{a(i)rate(i)+b(i)} \\ g_{2}(i)=\frac{f(i)}{rate(i)\times a(i)+b(i)} \\ $$

两个 $g$ 都没啥问题,主要来看 $f(i)$。提一下可得:

$$ f(i)=\max\{b(i)\max_{j=1}^{i-1}\{\frac{a(i)}{b(i)}g_{1}(j)+g_{2}(j)\},f(i-1)\} $$

斜率优化的形式,但斜率并无单调性。那个 $f(i-1)$ 可以最后来线性做,所以可以先不管。然后就是 li-chao tree 的板子。

#include<bits/stdc++.h>
std::vector<double> pri;
int n,nodes[400010];
double g[5][100010],f[100010],a[100010],b[100010],rate[100010],slp[100010];
double _f(int i,int j){return pri[i-1]*g[1][j]+g[2][j];}
void ins(int l,int r,int x,int i)
{
    if(l^r)
    {
        int mid=(l+r)>>1;
        if(_f(mid,i)>_f(mid,nodes[x]))    std::swap(nodes[x],i);
        if(_f(l,i)>_f(l,nodes[x]))    ins(l,mid,x<<1,i);
        else    ins(mid+1,r,x<<1|1,i);
    }
    else if(_f(l,i)>_f(l,nodes[x]))    nodes[x]=i;
}
double find(int l,int r,int x,int i)
{
    if(l^r)
    {
        int mid=(l+r)>>1;
        if(mid>=i)    return std::max(find(l,mid,x<<1,i),_f(i,nodes[x]));
        else    return std::max(find(mid+1,r,x<<1|1,i),_f(i,nodes[x]));
    }
    else    return _f(i,nodes[x]);
}
#define All(x) (x).begin(),(x).end()
int main()
{
    double pref=0,nowf=0;
    scanf("%d %lf",&n,&nowf);
    pref=nowf;
    for(int i=1;i<=n;++i)
    {
        scanf("%lf %lf %lf",&a[i],&b[i],&rate[i]);
        slp[i]=a[i]/b[i];
        pri.emplace_back(slp[i]);
    }
    std::sort(All(pri));
    for(int i=1;i<=n;++i)
    {
        nowf=std::max(pref,b[i]*find(1,n,1,std::lower_bound(All(pri),slp[i])-pri.begin()+1));
        g[1][i]=nowf*rate[i]/(a[i]*rate[i]+b[i]);
        g[2][i]=nowf/(a[i]*rate[i]+b[i]);
        ins(1,n,1,i);
        pref=nowf;
    }
    printf("%.3f\n",nowf);
    return 0;
}

Description

Link.

起床困难综合症 上树。

Solution

线段树维护,树剖上树。

具体题解有空再写,我要去睡觉了。

#include<bits/stdc++.h>
typedef unsigned long long ULL;
struct node {
    ULL one,zero;
    node(ULL A=0,ULL B=0) {
        one=A;
        zero=B;
    }
}nodes[400010],exnodes[400010],res,exres;
ULL poi[100010],opz;
int k,dep[100010],son[100010],hb[100010],fa[100010],dfn[100010],sjc,op[100010],n,m,rev[100010],siz[100010];
int head[100010],nxt[200010],to[200010],cntot,opt,opx,opy;
bool flag,exflag;
void addEdge(int one,int ano) {
    to[++cntot]=ano;
    nxt[cntot]=head[one];
    head[one]=cntot;
}
node merge(node one,node ano) {
    node res(~0ull);
    ULL tmp=one.one,extmp=~tmp;
    res.one=(tmp&ano.one)|(extmp&ano.zero);
    tmp=one.zero;
    extmp=~tmp;
    res.zero=(tmp&ano.one)|(extmp&ano.zero);
    return res;
}
void adj(ULL &x,ULL y,int id) {
    if(id==1) {
        x&=y;
    } else if(id==2) {
        x|=y;
    } else {
        x^=y;
    }
}
void build(int l,int r,int x) {
    if(l^r) {
        int mid=(l+r)>>1;
        build(l,mid,x<<1);
        build(mid+1,r,x<<1|1);
        nodes[x]=merge(nodes[x<<1],nodes[x<<1|1]);
        exnodes[x]=merge(exnodes[x<<1|1],exnodes[x<<1]);
    } else {
        nodes[x]=exnodes[x]=node(~0ull);
        adj(nodes[x].one,poi[rev[l]],op[rev[l]]);
        adj(nodes[x].zero,poi[rev[l]],op[rev[l]]);
        adj(exnodes[x].one,poi[rev[l]],op[rev[l]]);
        adj(exnodes[x].zero,poi[rev[l]],op[rev[l]]);
    }
}
void ins(int l,int r,int x,int pos,int aj,ULL val) {
    if(l^r) {
        int mid=(l+r)>>1;
        if(mid>=pos) {
            ins(l,mid,x<<1,pos,aj,val);
        } else {
            ins(mid+1,r,x<<1|1,pos,aj,val);
        }
        nodes[x]=merge(nodes[x<<1],nodes[x<<1|1]);
        exnodes[x]=merge(exnodes[x<<1|1],exnodes[x<<1]);
    } else {
        op[rev[l]]=aj;
        poi[rev[l]]=val;
        nodes[x]=exnodes[x]=node(~0ull);
        adj(nodes[x].one,poi[rev[l]],op[rev[l]]);
        adj(nodes[x].zero,poi[rev[l]],op[rev[l]]);
        adj(exnodes[x].one,poi[rev[l]],op[rev[l]]);
        adj(exnodes[x].zero,poi[rev[l]],op[rev[l]]);
    }
}
void find(int l,int r,int x,int fr,int ba) {
    if(l>ba || r<fr) {
        return;
    } else {
        if(l>=fr && r<=ba) {
            if(!flag) {
                res=nodes[x];
                flag=true;
            } else {
                res=merge(nodes[x],res);
            }
        } else {
            int mid=(l+r)>>1;
            find(mid+1,r,x<<1|1,fr,ba);
            find(l,mid,x<<1,fr,ba);
        }
    }
}
void exfind(int l,int r,int x,int fr,int ba) {
    if(l>ba || r<fr) {
        return;
    } else {
        if(l>=fr && r<=ba) {
            if(!exflag) {
                exres=exnodes[x];
                exflag=true;
            } else {
                exres=merge(exres,exnodes[x]);
            }
        } else {
            int mid=(l+r)>>1;
            exfind(mid+1,r,x<<1|1,fr,ba);
            exfind(l,mid,x<<1,fr,ba);
        }
    }
}
node LCA(int x,int y) {
    flag=exflag=false;
    res=exres=node(~0ull);
    while(hb[x]^hb[y]) {
        if(dep[hb[x]]>dep[hb[y]]) {
            exfind(1,n,1,dfn[hb[x]],dfn[x]);
            x=fa[hb[x]];
        } else {
            find(1,n,1,dfn[hb[y]],dfn[y]);
            y=fa[hb[y]];
        }
    }
    if(dep[x]<dep[y]) {
        find(1,n,1,dfn[x],dfn[y]);
    } else {
        exfind(1,n,1,dfn[y],dfn[x]);
    }
    return merge(exres,res);
}
void dfs1(int x,int las) {
    dep[x]=dep[las]+1;
    fa[x]=las;
    siz[x]=1;
    for(int i=head[x];i;i=nxt[i]) {
        int y=to[i];
        if(y^las) {
            dfs1(y,x);
            siz[x]+=siz[y];
            if(siz[son[x]]<siz[y]) {
                son[x]=y;
            }
        }
    }
}
void dfs2(int x,int t) {
    hb[x]=t;
    dfn[x]=++sjc;
    rev[sjc]=x;
    if(son[x]) {
        dfs2(son[x],t);
        for(int i=head[x];i;i=nxt[i]) {
            int y=to[i];
            if((y^fa[x]) && (y^son[x])) {
                dfs2(y,y);
            }
        }
    }
}
ULL solve(node now,ULL lim) {
    ULL res=0,run=0;
    for(int i=k-1;~i;--i) {
        if(now.zero&(1ull<<i)) {
            res+=(1ull<<i);
        } else if((now.one&(1ull<<i)) && run+(1ull<<i)<=lim) {
            run+=(1ull<<i);
            res+=(1ull<<i);
        }
    } 
    return res;
}
char fgc() {
    static char buf[1<<21],*p=buf,*q=buf;
    return p==q && (q=buf+fread(p=buf,1,1<<21,stdin),p==q)?EOF:*p++;
}
template<typename T>
void read(T &hhh) {
    T x=0;
    int f=0;
    char c=fgc();
    while(c<'0' || c>'9') {
        if(c=='-') {
            f=1;
        }
        c=fgc();
    }
    while(c>='0' && c<='9') {
        x=(x<<3)+(x<<1)+(c^'0');
        c=fgc();
    }
    if(f) {
        hhh=-x;
    } else {
        hhh=x;
    }
}
int wrstk[100];
template<typename T>
void write(T x,char las='\n') {
    int top=0,f=0;
    if(x<0) {
        x=-x;
        f=1;
    }
    do {
        wrstk[++top]=x%10;
        x/=10;
    } while(x);
    if(f) {
        putchar('-');
    }
    while(top) {
        putchar(wrstk[top--]^'0');
    }
    putchar(las);
}
int main() {
    read(n);
    read(m);
    read(k);
    for(int i=1;i<=n;++i) {
        read(op[i]);
        read(poi[i]);
    }
    for(int i=1,x,y;i<n;++i) {
        read(x);
        read(y);
        addEdge(x,y);
        addEdge(y,x);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,n,1);
    while(m-->0) {
        read(opt);
        read(opx);
        read(opy);
        read(opz);
        if(opt==1) {
            if(k) {
                write(solve(LCA(opx,opy),opz));
            } else {
                write(0);
            }
        } else {
            ins(1,n,1,dfn[opx],opy,opz);
        }
    }
    return 0;
}