gym 101986

A - Secret of Chocolate Poles

队友写的。 好像水水的。

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 998244353
#define ld long double
//#define C 0.5772156649
//#define ls l,m,rt<<1
//#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
//#define base 1000000000000000000
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const ull ba=233;
const db eps=1e-5;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=1000000+10,maxn=1000000+10,inf=0x3f3f3f3f;

ll dp[200][2];
int main()
{
    int l,k;scanf("%d%d",&l,&k);
    dp[1][1]=dp[k][1]=1;
    for(int i=1;i<=l;i++)
    {
        dp[i+1][0]+=dp[i][1];
        dp[i+1][1]+=dp[i][0];
        dp[i+k][1]+=dp[i][0];
    }
    ll ans=0;
    for(int i=1;i<=l;i++)ans+=dp[i][1];
    printf("%lld\n",ans);
    return 0;
}
/********************

********************/

C - Medical Checkup

队友写的。

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 998244353
#define ld long double
//#define C 0.5772156649
//#define ls l,m,rt<<1
//#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
//#define base 1000000000000000000
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const ull ba=233;
const db eps=1e-5;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=100000+10,maxn=1000000+10,inf=0x3f3f3f3f;

ll a[N];
int main()
{
    ll n,t;scanf("%lld%lld",&n,&t);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    ll ma=0,sum=0;
    for(int i=1;i<=n;i++)
    {
        ma=max(ma,a[i]);
        sum=sum+a[i];
        if(t<sum)printf("%d\n",1);
        else
        {
            ll te=(t-sum)/ma+2;
            printf("%lld\n",te);
        }
    }
    return 0;
}
/********************

********************/

B - Parallel Lines

dfs暴力枚举两两组合的情况, 枚举选第一个没被选的和枚举的组合, 这样能把复杂度降到最低。

然后答案一遍加入一遍更新, 好像我常数扣的有点厉害。 复杂度是15 * 13 * 11 * ... * 3

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 16 + 7;
const int M = 2000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

struct Point {
    int x, y;
} p[N];

int X[16][16], Y[16][16], all;
int num[4007][4007];
int n, cnt[1 << 16], who[1 << 16];
int ans, tmp;
vector<int> go[1 << 16];

inline void change(int x, int y, int op) {
    x += 2000, y += 2000;
    if(op == 1) tmp += num[x][y];
    else tmp -= num[x][y] - 1;
    num[x][y] += op;
}

void dfs(int S) {
    if(cnt[S] + 2 > n) {
        ans = max(ans, tmp);
        return;
    }
    for(int i = 1; i < SZ(go[S]); i++) {
        change(X[go[S][0]][go[S][i]], Y[go[S][0]][go[S][i]], 1);
        dfs(S | (1 << go[S][0]) | (1 << go[S][i]));
        change(X[go[S][0]][go[S][i]], Y[go[S][0]][go[S][i]], -1);
    }
}

int main() {
    for(int i = 1; i < (1 << 16); i++)
        cnt[i] = cnt[i - (i & -i)] + 1;
    scanf("%d", &n);
    all = n / 2;
    for(int i = 0; i < n; i++) {
        scanf("%d%d", &p[i].x, &p[i].y);
    }
    for(int i = 0; i < n; i++) {
        for(int j = i + 1; j < n; j++) {
            X[i][j] = p[i].x - p[j].x;
            Y[i][j] = p[i].y - p[j].y;
            int gcd = __gcd(X[i][j], Y[i][j]);
            X[i][j] /= gcd;
            Y[i][j] /= gcd;
            if(X[i][j] < 0) X[i][j] = -X[i][j], Y[i][j] = -Y[i][j];
//            printf("%d %d: %d %d\n", i, j, X[i][j], Y[i][j]);
        }
    }
    for(int i = 0; i < (1 << n); i++)
        for(int k = 0; k < n; k++)
            if(!(i >> k & 1)) go[i].push_back(k);
    dfs(0);
    printf("%d\n", ans);
    return 0;
}

/*
*/

I - Starting a Scenic Railroad Service

队友写的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>
#include<stack>
#include<string>
#include<map>
using namespace std;
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mst(x,a) memset(x,a,sizeof(x))
#define all(x) (x).begin(),(x).end()
#define CLOSE ios::sync_with_stdio(false)
typedef pair<int,int> pii;
typedef long long ll;
typedef vector<int> vi;
#define fi first
#define se second
#define sz(x) ((int)x.size())
#define cl(x) x.clear()
const int mod = 1000000007;
const int N = 200010;
const int INF=0x3f3f3f3f;
void MOD(ll &a){if(a>=mod) a-=mod;}
void MOD(ll &a,ll c){if(a>=c) a-=c;}
void ADD(ll &a,ll b){ a+=b; MOD(a);}
void ADD(ll &a,ll b,ll c){a+=b;MOD(a,c);}
ll qpow(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b/=2;}return ans;}
ll qpow(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c;b/=2;}return ans;}

int n;
int x[N],y[N],B[N];

struct seg{
    int l,r;
}a[N],b[N];

bool cmp1(seg a,seg b){
    if(a.l==b.l) return a.r<b.r;
    return a.l<b.l;
}

bool cmp2(seg a,seg b){
    if(a.r==b.r) return a.l<b.l;
    return a.r<b.r;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&x[i],&y[i]);
        y[i]--;
        B[x[i]]++; B[y[i]+1]--;
        a[i].l=x[i]; a[i].r=y[i];
        b[i].l=x[i]; b[i].r=y[i];
    }
    sort(a+1,a+1+n,cmp1);
    sort(b+1,b+1+n,cmp2);

    int ans1=0,ans2=0;
    for(int i=1;i<=100001;i++){
        B[i]+=B[i-1]; ans2=max(ans2,B[i]);
    }
    //a sort by l    b sort by r
    for(int i=1;i<=n;i++){
        int tmp=n;
        int l=1,r=n+1;
        while(l+1<r){
            int m=l+r>>1;
            if(a[m].l>y[i]) r=m;
            else l=m;
        }
        tmp-=n-r+1;
        l=0,r=n;
        while(l+1<r){
            int m=l+r>>1;
            if(b[m].r<x[i]) l=m;
            else r=m;
        }
        tmp-=l;
        ans1=max(ans1,tmp);
    }

    printf("%d %d\n",ans1,ans2);
}
/*
*/

F - Pizza Delivery

感觉是比较常规的套路题。

把边(u, v, w)反转以后如果 dis[ 1 ][ v ] + dis[ 2 ][ u ] + w < 最短路则是happy, 这里有个问题就是反转之后1到不了v, 但是反转前到到的了,

那么dis[ 1 ][ v ] 就不是INF, 但是通过分析我们能发现这不影响结果。

然后就是 sad 和 soso, 这个对 1 到 2 之间的最短路图求个桥就好了,看看反转的是不是桥。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

int n, m, a[N], b[N], c[N];
LL dis[2][N];
bool flag[N];

struct node {
    LL d;
    int to, id;
    bool operator < (const node& rhs) const {
        return d > rhs.d;
    }
};

vector<node> G[N], rG[N], sG[N];

priority_queue<node> que;

void Dij(int S, LL dis[N]) {
    dis[S] = 0;
    que.push(node{0, S, 0});
    while(!que.empty()) {
        int u = que.top().to;
        LL d = que.top().d; que.pop();
        if(d > dis[u]) continue;
        for(auto& t : G[u]) {
            if(d + t.d < dis[t.to]) {
                dis[t.to] = d + t.d;
                que.push(node{dis[t.to], t.to, 0});
            }
        }
    }
}

void Dij2(int S, LL dis[N]) {
    dis[S] = 0;
    que.push(node{0, S, 0});
    while(!que.empty()) {
        int u = que.top().to;
        LL d = que.top().d; que.pop();
        if(d > dis[u]) continue;
        for(auto& t : rG[u]) {
            if(d + t.d < dis[t.to]) {
                dis[t.to] = d + t.d;
                que.push(node{dis[t.to], t.to, 0});
            }
        }
    }
}

int dfn[N], low[N], idx;
bool in[N];

void tarjan(int u, int fa) {
    in[u] = true; ++idx;
    dfn[u] = low[u] = idx;
    for(node& t : sG[u]) {
        int v = t.to;
        if(v == fa) continue;
        if(!dfn[v]) {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if(dfn[u] < low[v]) flag[t.id] = true;
        } else if(in[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    in[u] = false;
}

int main() {
    memset(dis, INF, sizeof(dis));
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++) {
        scanf("%d%d%d", &a[i], &b[i], &c[i]);
        G[a[i]].push_back(node{c[i], b[i], i});
        rG[b[i]].push_back(node{c[i], a[i], i});
    }
    Dij(1, dis[0]);
    Dij2(2, dis[1]);
    LL mn = dis[0][2];
    if(mn != INF) {
        for(int i = 1; i <= n; i++) {
            for(node t : G[i]) {
                if(t.d + dis[0][i] + dis[1][t.to] == mn) {
                    sG[i].push_back(t);
                    sG[t.to].push_back(node{t.d, i, t.id});
                }
            }
        }
        tarjan(1, 0);
        for(int i = 1; i <= m; i++) {
            if(dis[0][b[i]] + dis[1][a[i]] + c[i] < mn) {
                puts("HAPPY");
            } else {
                if(flag[i]) puts("SAD");
                else puts("SOSO");
            }
        }
    } else {
        for(int i = 1; i <= m; i++) {
            if(dis[0][b[i]] + dis[1][a[i]] + c[i] < mn) {
                puts("HAPPY");
            } else {
                puts("SAD");
            }
        }
    }
    return 0;
}

/*
*/

赛后补题**********************************************************************************************************************************************

G - Rendezvous on a Tetrahedron

训练结束半个多小时才码出来。。。 把四面体展开, 然后暴力的取找到它最后的位置在哪里, 好像有更方便的方法, 我写得好麻烦啊啊。。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

struct Point {
    double x, y;
    void print() {
        printf("%.3f %.3f ^^\n", x, y);
    }
    Point(double x = 0, double y = 0) : x(x), y(y) { }
};
typedef Point Vector;

int dcmp(double x) {
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}

Point operator + (Vector A, Vector B) {return Point(A.x + B.x, A.y + B.y);}
Point operator - (Vector A, Vector B) {return Point(A.x - B.x, A.y - B.y);}
Point operator * (Vector A, double p) {return Point(A.x * p, A.y * p);}
Point operator / (Vector A, double p) {return Point(A.x / p, A.y / p);}
bool operator < (const Vector &A, const Vector &B) {return A.y < B.y || (A.y == B.y && A.x < B.x);}
bool operator == (const Vector &A, const Point &B) {return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0;}
double Dot(Vector A, Vector B) {return A.x * B.x + A.y * B.y;}
double Length(Vector A) {return sqrt(Dot(A, A));}
double Angle(Vector A, Vector B) {return acos(Dot(A, B) / Length(A) / Length(B));}
double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}
double Area2(Point A, Point B, Point C) {return Cross(B - A, C - A);}

Vector Rotate(Vector A, double rad) {
    return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
}

double GetLineIntersectionTime(Point P, Vector v, Point Q, Vector w) {
    Vector u = P - Q;
    double t = Cross(w, u) / Cross(v, w);
    return t;
}

double dist(const Point& a, const Point &b) {
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}

bool isPointOnSegment(const Point &p, const Point &a1, const Point &a2)
{
    if(dcmp(Cross(a1-p,a2-p))) return 0;
    else if(dcmp(p.x-min(a1.x,a2.x))>=0&&dcmp(p.x-max(a1.x,a2.x))<=0
            &&dcmp(p.y-min(a1.y,a2.y))>=0&&dcmp(p.y-max(a1.y,a2.y))<=0) return 1;
    else return 0;
}

int isPointInPolygon(Point p, Point *poly, int n) {
    int wn = 0;
    for(int i = 0; i < n; i++) {
        if(isPointOnSegment(p, poly[i], poly[(i+1)%n])) return -1; //在边界上
        int k = dcmp(Cross(poly[(i+1)%n]-poly[i], p-poly[i]));
        int d1 = dcmp(poly[i].y-p.y);
        int d2 = dcmp(poly[(i+1)%n].y-p.y);
        if(k>0 && d1<=0 && d2>0) wn++;
        if(k<0 && d2<=0 && d1>0) wn--;
    }
    if(wn != 0) return 1; //内部
    return 0; //外部
}

Point A2 = Point(0, 0);
Point A3 = Point(2, 0);
Point A1 = Point(1, sqrt(3.0));
Point D = (A1 + A2) / 2;
Point B = (A1 + A3) / 2;
Point C = (A2 + A3) / 2;

Point poly1[] = {A1, D, B};
Point poly2[] = {D, C, B};
Point poly3[] = {D, A2, C};
Point poly4[] = {B, C, A3};

bool isA12(Point x) {
    return isPointOnSegment(x, A1, A2);
}
bool isA23(Point x) {
    return isPointOnSegment(x, A2, A3);
}
bool isA31(Point x) {
    return isPointOnSegment(x, A3, A1);
}
int belong(Point x) {
    if(isPointInPolygon(x, poly1, 3) == 1) return 1;
    if(isPointInPolygon(x, poly2, 3) == 1) return 2;
    if(isPointInPolygon(x, poly3, 3) == 1) return 3;
    if(isPointInPolygon(x, poly4, 3) == 1) return 4;
}

Point dfs(Point p, Vector v, double len) {
    if(isA12(p)) {
        double t1 = GetLineIntersectionTime(p, v, A2, A3 - A2);
        double t2 = GetLineIntersectionTime(p, v, A1, A3 - A1);
        Point nxtp;
        if(dcmp(t1) > 0 && (dcmp(t2) <= 0 || dcmp(t1) > 0 && t1 < t2)) {
            nxtp = p + (v * t1);
            double gg = dist(p, nxtp);
            if(dcmp(len - gg) < 0) {
                return p + (v / Length(v)) * len;
            } else {
                nxtp = C * 2.0 - nxtp;
                v = Rotate(v, PI);
                return dfs(nxtp, v, len - gg);
            }
        } else {
            nxtp = p + v * t2;
            double gg = dist(p, nxtp);
            if(dcmp(len - gg) < 0) {
                return p + (v / Length(v)) * len;
            } else {
                nxtp = B * 2.0 - nxtp;
                v = Rotate(v, PI);
                return dfs(nxtp, v, len - gg);
            }
        }
    } else if(isA23(p)) {
        double t1 = GetLineIntersectionTime(p, v, A1, A1 - A2);
        double t2 = GetLineIntersectionTime(p, v, A1, A1 - A3);
        Point nxtp;
        if(dcmp(t1) > 0 && (dcmp(t2) <= 0 || dcmp(t1) > 0 && t1 < t2)) {
            nxtp = p + v * t1;
            double gg = dist(p, nxtp);
            if(dcmp(len - gg) < 0) {
                return p + (v / Length(v)) * len;
            } else {
                nxtp = D * 2.0 - nxtp;
                v = Rotate(v, PI);
                return dfs(nxtp, v, len - gg);
            }
        } else {
            nxtp = p + v * t2;
            double gg = dist(p, nxtp);
            if(dcmp(len - gg) < 0) {
                return p + (v / Length(v)) * len;
            } else {
                nxtp = B * 2.0 - nxtp;
                v = Rotate(v, PI);
                return dfs(nxtp, v, len - gg);
            }
        }
    } else if(isA31(p)) {
        double t1 = GetLineIntersectionTime(p, v, A2, A2 - A1);
        double t2 = GetLineIntersectionTime(p, v, A2, A2 - A3);
        Point nxtp;
        if(dcmp(t1) > 0 && (dcmp(t2) <= 0 || dcmp(t1) > 0 && t1 < t2)) {
            nxtp = p + v * t1;
            double gg = dist(p, nxtp);
            if(dcmp(len - gg) < 0) {
                return p + (v / Length(v)) * len;
            } else {
                nxtp = D * 2.0 - nxtp;
                v = Rotate(v, PI);
                return dfs(nxtp, v, len - gg);
            }
        } else {
            nxtp = p + v * t2;
            double gg = dist(p, nxtp);
            if(dcmp(len - gg) < 0) {
                return p + (v / Length(v)) * len;
            } else {
                nxtp = C * 2.0 - nxtp;
                v = Rotate(v, PI);
                return dfs(nxtp, v, len - gg);
            }
        }
    }
}

Point read() {
    char s[10];
    double d, l;
    scanf("%s%lf%lf", s, &d, &l);
    if(s[0] == ‘C‘ && s[1] == ‘D‘) {
        Point startp = A2;
        Vector startv = Rotate(C - A2, d / 180 * PI);
        return dfs(startp, startv, l);
    } else if(s[0] == ‘D‘ && s[1] == ‘B‘) {
        Point startp = A1;
        Vector startv = Rotate(D - A1, d / 180 * PI);
        return dfs(startp, startv, l);
    } else {
        Point startp = A3;
        Vector startv = Rotate(B - A3, d / 180 * PI);
        return dfs(startp, startv, l);
    }
}

int main() {
    Point Point1 = read();
    Point Point2 = read();
    if(belong(Point1) == belong(Point2)) puts("YES");
    else puts("NO");
    return 0;
}

/*
*/

E - Black or White

不会写, 但是看了题解觉得好有道理啊啊啊, 我怎么没想到呢。

我们把t[ i ] == s[ i ]的位置的颜色保留, 把颜色不同的当成没有颜色就好了。

我们定义dp[ i ] 表示把 1 - i 全部染成对应颜色所需要的次数。

我们把 t 中连续相同的一段看成一个整体。变成 WBWBWB的形式, 如果长度为 m 则答案为 (m / 2) + 1

如果t[ i ] == s[ i ]      dp[ i ] = dp[ i - 1]

否则                         dp[ i ] = min(dp[ j ] + (sum[ i ] - sum[ j + 1 ]) / 2 + 1)

很显然能发现能用单调队列优化。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 5e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

int n, k, head, rear, sum[N], que[N];
int dp[N];
char s[N], t[N];

int main() {
    scanf("%d%d", &n, &k);
    scanf("%s%s", s + 1, t + 1);
    for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + (t[i] != t[i - 1]);
    head = 1, rear = 0;
    dp[0] = 0;
    que[++rear] = 0;
    for(int i = 1; i <= n; i++) {
        if(t[i] == s[i]) {
            dp[i] = dp[i - 1];
        } else {
            while(head <= rear && i - que[head] > k) head++;
            dp[i] = dp[que[head]] + (sum[i] - sum[que[head] + 1] + 1) / 2 + 1;
        }
        while(head <= rear && 2*dp[i] - sum[i + 1] <= 2*dp[que[rear]] - sum[que[rear] + 1]) rear--;
        que[++rear] = i;
    }
    printf("%d\n", dp[n]);
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/10420792.html

时间: 2024-11-09 16:34:42

gym 101986的相关文章

CodeForces Gym 100935D Enormous Carpet 快速幂取模

Enormous Carpet Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Gym 100935D Description standard input/outputStatements Ameer is an upcoming and pretty talented problem solver who loves to solve problems using computers.

B - Average Gym - 101161B 组合数学

http://codeforces.com/gym/101161/attachments 今天被卡常了,其实是自己对组合数技巧研究的不够. 如果是n, m <= 1e5的,然后取模是质数,那么可以用费马小定理. 如果n, m都比较小,那么其实是直接杨辉三角.不用逆元那些. 这题的思路是,枚举每一一个ave,然后总和就是n * ave 相当于方程  x1 + x2 + .... + xn = n * ave中,在0 <= x[i] <= full的情况下,不同解的个数中,使得x[i] ==

Codeforces Gym 100269 Dwarf Tower (最短路)

题目连接: http://codeforces.com/gym/100269/attachments Description Little Vasya is playing a new game named "Dwarf Tower". In this game there are n different items,which you can put on your dwarf character. Items are numbered from 1 to n. Vasya want

CodeForces Gym 101063C 二进制压缩

http://codeforces.com/gym/101063/problem/C 给n个人,m样物品,每个人可以从物品中选择几样.两人选择物品的交集元素个数比上并集元素个数如果大于某个比例即可将两人配对.求配对数. n的范围是1e5,直接比较所有人的选择会TLE,应该将所有选择物品的情况用二进制压缩,m最大是10,情况数目小于2048,可以接受.注意配对总数范围应为long long. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> i

Gym 101246H ``North-East&#39;&#39;(LIS)

http://codeforces.com/gym/101246/problem/H 题意: 给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点.输出它可能经过的点和一定会经过的点. 思路: 分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走. 观察一下,就可以发现这道题目就是要我们求一个LIS. 首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面. 用二分法求LIS,这样在d数组中就可

Gym 100712I Bahosain and Digits(开关翻转问题)

http://codeforces.com/gym/100712/attachments 题意: 给出一串数字,每次选择连续的k个数字加上任意数(超过10就取余),最后要使得所有数字都相等,求最大的k. 思路: 开关翻转问题. 算法具体可以参考<挑战程序竞赛>常用技巧篇. 这道题目就是在枚举k的同时再枚举一下最后要转换成的数字即可. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring>

很好的脑洞题:dfs+暴力 Gym - 101128A Promotions

http://codeforces.com/gym/101128 题目大意:给你一个a,b,e,p.有e个点,p条有向边,每条边为(x,y),表示x->y,每次我们都取出一个入度为0的,并且一次性取出来的个数为a(或b).当然,取出来的种类可能有很多种(即一个集合),问,这个集合中有多少个数字是相同的. 第一个输出集合长度为a的,第二个输出集合长度为b的,第三个输出无论如何都无法被取出的个数. 思路:建立正向图和反向图. 定义pair<int, int> interval[i] 表示第i

【树状数组】Gym - 101147J - Whistle&#39;s New Car

题意就是对每个点i,统计在其子树内(不含自身),且depj-depi<=xj的点有多少个. 把点分别按照dep-x和dep进行排序,离线处理, 每次把dep-x小于等于当前dep值的点插入树状数组,就变成了询问dfs序在一个区间内的点有多少个,可以用树状数组轻松解决. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int f,C; void R(int &am

SYSU-7, Gym 100273J, trie+hash

cnm毛子的题是正宗内家拳法啊orz(捶地),拼的就是智商,这题我们队想了老半天后缀自动机,掏出各种黑科技无果 题目大意:构建一个自动机可以表达给定的n个串,询问最小的自动机节点树为多少. 解:最裸的自动机其实就是一棵trie,那么我们考虑优化这棵trie,考虑拓扑排序倒过来做,可以发现其实如果两个节点如果他们指向的节点状态完全一致,那么这两个节点是等价的,所以我们不断合并这些节点即可.但是拓扑可能会慢,而且貌似会退化n方(没细想),但一般地,我们用dfs出栈序去做这个hash去重即可. cnm