26.10.6qbxt集训day6

T1

image
考虑固定全选三线射手,二分最小火力。
发现可以check。

点击查看代码
#include <iostream>

using std::cin;
using std::cout;
const int N = 1e6 + 10;
typedef long long ll;

int n;
ll a[N];
ll now[N];
ll b[N];

bool check(ll mid)
{
	for (int i = 1; i <= n; ++i)
		now[i] = b[i];
	for (int i = 1; i <= n; ++i)
	{
		if (now[i] >= mid)
			continue;
		if (i == 1)
		{
			now[i + 1] -= std::min(mid - now[i], a[i]);
			now[i] += std::min(mid - now[i], a[i]);
		}
		else
		{
			now[i + 1] -= std::min(std::min(now[i - 1] - mid, mid - now[i]), a[i]);
			now[i] += std::min(std::min(now[i - 1] - mid, mid - now[i]), a[i]);
		}
		if (now[i] < mid)
			return false;
	}
	return true;
}
template<typename T>
void rd(T &x)
{
	x = 0;
	int f = 1;
	char c = getchar();
	while (!isdigit(c))
	{
		if (c == '-')
			f = -f;
		c = getchar();
	}
	while (isdigit(c))
	{
		x = (x << 3) + (x << 1) - '0' + c;
		c = getchar();
	}
	x *= f;
}

int main()
{
	freopen("pea.in", "r", stdin);
	freopen("pea.out", "w", stdout);
	rd(n);
	for (int i = 1; i <= n; ++i)
		rd(a[i]);
	for (int i = 1; i <= n; ++i)
		b[i] = a[i - 1] + a[i] + a[i + 1];
	ll l = 0, r = 1e14;
	ll mid;
	ll ans;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if (check(mid))
		{
			ans = mid;
			l = mid + 1;
		}
		else
			r = mid - 1;
	}
	cout << ans << '\n';
	return 0;9
}

T2

image
考虑到如果没有 \(2\) 一定无解。
然后固定选一个 \(2\),枚举其它两个数 \(a_i, a_j\)。
要求出一组 \(x,y\) 使得 \(a_ix,a_jy\) 都是奇数,且 \(a_jy = a_ix + 2\)。
直接 exgcd。

点击查看代码
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>

using std::cin;
using std::cout;
const int N = 1e3 + 10;
typedef long long ll;
struct Node
{
	int p;
	int a;
	friend bool operator<(const Node &a, const Node &b)
	{
		return a.a < b.a;
	}
} a[N];

int ans[4];

void exgcd(int a, int b, ll &x, ll &y)
{
	if (b == 0)
		return x = 1, y = 0, void();
	exgcd(b, a % b, y, x);
	y -= 1ll * a / b * x;
}
int gcd(int x, int y)
{
	if (!x || !y)
		return x | y;
	int xx = __builtin_ctz(x);
	int yy = __builtin_ctz(y);
	int k = std::min(xx, yy);
	int tmp;
	y >>= yy;
	while (x)
	{
		x >>= xx;
		tmp = y - x;
		xx = __builtin_ctz(tmp);
		y = std::min(x, y), x = abs(tmp);
	}
	return y << k;
}
void rd(int &x)
{
	x = 0;
	int f = 1;
	char c = getchar();
	while (!isdigit(c))
	{
		if (c == '-')
			f = -f;
		c = getchar();
	}
	while (isdigit(c))
	{
		x = (x << 3) + (x << 1) - '0' + c;
		c = getchar();
	}
	x *= f;
}

int main()
{
	freopen("multiple.in", "r", stdin);
	freopen("multiple.out", "w", stdout);
	int n;
	rd(n);
	for (int i = 1; i <= n; ++i)
		rd(a[i].a), a[i].p = i;
	std::sort(a + 1, a + n + 1);
	if (n < 3)
	{
		cout << "NO" << '\n';
		return 0;
	}
	if (a[1].a == 1)
	{
		cout << "YES" << '\n';
		ans[1] = a[1].p;
		ans[2] = a[2].p;
		ans[3] = a[3].p;
		std::sort(ans + 1, ans + 3 + 1);
		cout << ans[1] << ' ' << ans[2] << ' ' << ans[3] << '\n';
		cout << 1 << '\n';
		return 0;
	}
	if (a[1].a == 2)
	{
		for (int i = 2; i <= n; ++i)
		{
			for (int j = 2; j <= n; ++j)
			{
				if (i == j)
					continue;
				if ((!(a[i].a & 1)) || (!(a[j].a & 1)))
					continue;
				if (gcd(a[i].a, a[j].a) != 1)
					continue;
				ll x, y;
				exgcd(a[i].a, a[j].a, x, y);
				x = (x << 1);
				y = (y << 1);
				x = -x;
				if (x <= 0)
				{
					ll t = (-x + a[j].a - 1) / a[j].a;
					x += t * a[j].a, y += t * a[i].a;
					if (x <= 0)
						x += a[j].a, y += a[i].a;
				}
				if (y <= 0)
				{
					ll t = (-y + a[i].a - 1) / a[i].a;
					x += t * a[j].a, y += t * a[i].a;
					if (y <= 0)
						x += a[j].a, y += a[i].a;
				}
				if (!(x & 1))
					x += a[j].a, y += a[i].a;
				if (x <= ((ll)1e18 + 1) / a[i].a)
				{
					cout << "YES" << '\n';
					ans[1] = a[1].p;
					ans[2] = a[i].p;
					ans[3] = a[j].p;
					std::sort(ans + 1, ans + 3 + 1);
					cout << ans[1] << ' ' << ans[2] << ' ' << ans[3] << '\n';
					cout << x * a[i].a - 1 << '\n';
					return 0;
				}
			}
		}
	}
	cout << "NO" << '\n';
	return 0;
}

T3

image
似乎是懂了。

点击查看std
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;

struct FastInput {
    static constexpr int S = 1 << 16;
    char buf[S]; int p = 0, len = 0;
    inline char get() {
        if (p == len) {
            len = (int)fread(buf, 1, S, stdin); p = 0;
            if (!len) return 0;
        }
        return buf[p++];
    }
    template<class T> inline void read(T &x) {
        char c; do { c = get(); } while (c && c <= ' ');
        x = 0; for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
    }
} input;

constexpr int MAXK = 3000000;
int n, q;
vector<i64> D, P, Q; // P_i = W_i-u_i, Q_i = W_i+v_i

// All products fit in signed 64 bits under the stated constraints.
inline i64 cross(int a, int b, int c, const vector<i64> &Y) {
    return (D[b]-D[a])*(Y[c]-Y[a])-(Y[b]-Y[a])*(D[c]-D[a]);
}
inline bool slopeLess(int l1, int r1, int l2, int r2) {
    return (Q[r1]-P[l1])*(D[r2]-D[l2])
         < (Q[r2]-P[l2])*(D[r1]-D[l1]);
}
inline void pushUpper(vector<int> &h, int i) {
    while (h.size() > 1 && cross(h[h.size()-2], h.back(), i, P) >= 0)
        h.pop_back();
    h.push_back(i);
}
inline void pushLowerReverse(vector<int> &h, int i) {
    while (h.size() > 1 && cross(h[h.size()-2], h.back(), i, Q) >= 0)
        h.pop_back();
    h.push_back(i);
}
int tangentLeft(const vector<int> &h, int r) {
    int lo = 0, hi = (int)h.size()-1;
    while (lo < hi) {
        int m = (lo+hi)/2;
        if (slopeLess(h[m+1], r, h[m], r)) lo = m+1;
        else hi = m;
    }
    int l = h[lo];
    return (int)min<i64>(MAXK, (Q[r]-P[l])/(D[r]-D[l]));
}
int tangentRight(int l, const vector<int> &h) {
    int lo = 0, hi = (int)h.size()-1;
    while (lo < hi) {
        int m = (lo+hi)/2;
        if (slopeLess(l, h[m+1], l, h[m])) lo = m+1;
        else hi = m;
    }
    int r = h[lo];
    return (int)min<i64>(MAXK, (Q[r]-P[l])/(D[r]-D[l]));
}

struct Node {
    int lo=0, hi=0, lc=-1, rc=-1, group=-1;
    vector<int> prefix, suffix;
};
vector<Node> tree;
struct Group { int node; vector<int> byLeft, byRight; };
vector<Group> groups;
int build(int l, int r) {
    int id = (int)tree.size(); tree.emplace_back();
    tree[id].lo=l; tree[id].hi=r;
    if (l==r) return id;
    int mid=(l+r)/2;
    int lc=build(l,mid), rc=build(mid+1,r);
    Node &t=tree[id]; t.lc=lc; t.rc=rc;
    int size=r-l+1;
    t.prefix.resize(size); t.suffix.resize(size);
    vector<int> h; h.reserve(min(size,64));
    int best=MAXK;
    for (int i=l; i<=r; ++i) {
        if (i>l) best=min(best,tangentLeft(h,i));
        t.prefix[i-l]=best;
        pushUpper(h,i);
    }
    h.clear(); best=MAXK;
    for (int i=r; i>=l; --i) {
        if (i<r) best=min(best,tangentRight(i,h));
        t.suffix[i-l]=best;
        pushLowerReverse(h,i);
    }
    return id;
}
inline int prefixAnswer(int node, int r) {
    const Node &t=tree[node];
    return t.prefix.empty() ? MAXK : t.prefix[r-t.lo];
}
inline int suffixAnswer(int node, int l) {
    const Node &t=tree[node];
    return t.suffix.empty() ? MAXK : t.suffix[l-t.lo];
}

struct Query { int l, r, lo, hi, test; };
vector<Query> queries;
vector<i64> leftVal;

// The left points are inserted from mid down to l. This is an upper hull
// in decreasing X; the orientation sign is reversed from pushUpper().
inline void pushLeftReverse(vector<int> &h, int i) {
    while (h.size()>1 && cross(h[h.size()-2],h.back(),i,P)<=0)
        h.pop_back();
    h.push_back(i);
}
inline void pushRight(vector<int> &h, int i) {
    while (h.size()>1 && cross(h[h.size()-2],h.back(),i,Q)<=0)
        h.pop_back();
    h.push_back(i);
}
inline i64 lineP(int i, int k) { return P[i]-(i64)k*D[i]; }
inline i64 lineQ(int i, int k) { return Q[i]-(i64)k*D[i]; }
inline i64 maxLeft(const vector<int> &h, int k) {
    int lo=0, hi=(int)h.size()-1;
    while (lo<hi) {
        int m=(lo+hi)/2;
        if (lineP(h[m+1],k)>lineP(h[m],k)) lo=m+1;
        else hi=m;
    }
    return lineP(h[lo],k);
}
inline i64 minRight(const vector<int> &h, int k) {
    int lo=0, hi=(int)h.size()-1;
    while (lo<hi) {
        int m=(lo+hi)/2;
        if (lineQ(h[m+1],k)<lineQ(h[m],k)) lo=m+1;
        else hi=m;
    }
    return lineQ(h[lo],k);
}

// One parallel binary-search round. A query is assigned to exactly one node.
// Sweeps replace range-hull queries: O(size + active_queries * log size) per node.
void roundCheck(bool initial) {
    vector<int> hull;
    for (Group &g: groups) {
        Node &t=tree[g.node];
        int mid=tree[t.lc].hi;
        bool active=false;
        for (int id:g.byLeft) if (queries[id].lo<queries[id].hi) {active=true;break;}
        if (!active) continue;
        hull.clear();
        int pos=mid;
        for (int id:g.byLeft) {
            Query &z=queries[id];
            if (z.lo==z.hi) continue;
            while (pos>=z.l) {pushLeftReverse(hull,pos);--pos;}
            z.test=initial ? z.hi : z.lo+(z.hi-z.lo+1)/2;
            leftVal[id]=maxLeft(hull,z.test);
        }
        hull.clear(); pos=mid+1;
        for (int id:g.byRight) {
            Query &z=queries[id];
            if (z.lo==z.hi) continue;
            while (pos<=z.r) {pushRight(hull,pos);++pos;}
            bool ok=leftVal[id]<=minRight(hull,z.test);
            if (initial) {
                if (ok) z.lo=z.hi;
                else --z.hi;
            } else if (ok) z.lo=z.test;
            else z.hi=z.test-1;
        }
    }
}

int main() {
    input.read(n); input.read(q);
    vector<int> U(n),V(n);
    for (int &x:U) input.read(x);
    for (int &x:V) input.read(x);
    D.resize(n); vector<i64> W(n);
    for (int i=1;i<n;++i) {int x;input.read(x);D[i]=D[i-1]+x;}
    for (int i=1;i<n;++i) {int x;input.read(x);W[i]=W[i-1]+x;}
    P.resize(n); Q.resize(n);
    for (int i=0;i<n;++i) {P[i]=W[i]-U[i];Q[i]=W[i]+V[i];}
    vector<int>().swap(U);vector<int>().swap(V);vector<i64>().swap(W);

    tree.reserve(2*n);
    int root=build(0,n-1);
    queries.resize(q);leftVal.resize(q);
    for (int id=0;id<q;++id) {
        int l,r;input.read(l);input.read(r);--l;--r;
        int p=root;
        while (true) {
            const Node &t=tree[p];
            int mid=tree[t.lc].hi;
            if (r<=mid) p=t.lc;
            else if (l>mid) p=t.rc;
            else break;
        }
        Node &t=tree[p];
        int cap=min(suffixAnswer(t.lc,l),prefixAnswer(t.rc,r));
        queries[id]={l,r,0,cap,0};
        if (cap>0) {
            if (t.group<0) {t.group=(int)groups.size(); groups.push_back({p,{},{}});}
            groups[t.group].byLeft.push_back(id);
            groups[t.group].byRight.push_back(id);
        }
    }
    for (Group &g:groups) {
        sort(g.byLeft.begin(),g.byLeft.end(),[](int a,int b){return queries[a].l>queries[b].l;});
        sort(g.byRight.begin(),g.byRight.end(),[](int a,int b){return queries[a].r<queries[b].r;});
    }
    roundCheck(true); // First test the internal-interval upper bound.
    for (int pass=0;pass<22;++pass) roundCheck(false);
    string output;output.reserve(q*9);
    for (const Query &z:queries) {output+=to_string(z.lo);output+='\n';}
    fwrite(output.data(),1,output.size(),stdout);
}


T4

image
不懂

点击查看std
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
constexpr ll NEG=LLONG_MIN/4;
struct Edge{int v;ll w;};
struct Child{int v;ll w;};
int n,K;vector<vector<Edge>> adj;
mt19937 rng(20260927);
// f[j][0/1]: maximum weight, with j edges and structural sign +1/-1.
using DP=vector<array<ll,2>>;
inline void relax(ll &x,ll y){if(x<y)x=y;}
DP dfs(int u,int p){
    vector<Child> ch;for(auto e:adj[u])if(e.v!=p)ch.push_back({e.v,e.w});
    shuffle(ch.begin(),ch.end(),rng);
    int d=(int)ch.size();
    // A fixed optimal solution survives all these windows with probability >= 1-1e-10.
    // Hoeffding for samples without replacement, union-bound over all prefixes/nodes.
    int W=min(d+2,(int)ceil(sqrt(d*log(2.0*n*n*1e10)))+4);
    int width=2*W+1;
    vector<vector<ll>> cur(1,vector<ll>(width,NEG));cur[0][W]=0;
    int total=0,processed=0;
    for(auto e:ch){
        DP f=dfs(e.v,u);
        int lim=min(K,total+(int)f.size());
        vector<vector<ll>> nxt(lim+1,vector<ll>(width,NEG));
        for(int i=0;i<(int)cur.size();++i){
            int r=min(processed,W);
            for(int j=0;j<(int)f.size()&&i+j<=K;++j){
                ll a=f[j][0],z=f[j][1],base=max(a,z);
                int goal=i+j;
                for(int b=-r;b<=r;++b){
                    ll old=cur[i][W+b];if(old==NEG)continue;
                    if(base!=NEG)relax(nxt[goal][W+b],old+base);
                    if(goal+1<=K){
                        if(a!=NEG&&b+1<=W)relax(nxt[goal+1][W+b+1],old+a+e.w);
                        if(z!=NEG&&b-1>=-W)relax(nxt[goal+1][W+b-1],old+z+e.w);
                    }
                }
            }
        }
        cur=move(nxt);total=min(K,total+(int)f.size());++processed;
    }
    DP result(cur.size(),{NEG,NEG});
    for(int j=0;j<(int)cur.size();++j){result[j][0]=cur[j][W];if(W>=2)result[j][1]=cur[j][W+2];}
    return result;
}
int main(){
#ifdef FILE_IO
    freopen("matching.in","r",stdin);freopen("matching.out","w",stdout);
#endif
    ios::sync_with_stdio(false);cin.tie(nullptr);
    if(!(cin>>n>>K))return 0;adj.resize(n+1);
    for(int i=1,u,v;i<n;++i){ll w;cin>>u>>v>>w;adj[u].push_back({v,w});adj[v].push_back({u,w});}
    if(K&1){cout<<"Impossible\n";return 0;}
    auto f=dfs(1,0);ll ans=NEG;if(K<(int)f.size())ans=max(f[K][0],f[K][1]);
    if(ans==NEG)cout<<"Impossible\n";else cout<<ans<<'\n';
}



题解和今天讲的题:https://files.cnblogs.com/files/blogs/832279/2026_10_6_slide.zip?t=1791284375&download=true
image
从下往上读。

posted @ 2026-10-06 14:03  SigmaToT  阅读(7)  评论(0)    收藏  举报