1 条题解

  • 0
    @ 2026-5-3 7:59:23

    :::::info[闲话] 神秘组合刻画题。
    ::::: :::::info[题目基本信息] 考察:Ad-hoc(省选/NOI-)。
    题目简介:
    给定 nn 个物品,每个物品有权值,权值构成序列 {wn}\{w_n\}qq 次询问,每次询问给定 k,a,bk,a,b,假想有两个初始为 00 的数 x,yx,y,对于所有 wikw_i\le k 的物品,你可以选择令 xx+wix\leftarrow x+w_i,也可以选择令 yy+wiy\leftarrow y+w_i,也可以不操作。最终问对于所有 a[0,a],b[0,b]a'\in[0,a],b'\in[0,b](x,y)(x,y) 是否都能通过操作变成 (a,b)(a',b')
    强制在线。
    数据范围:

    • 1n,q3×1051\le n,q\le 3\times 10^5
    • i[1,n],1wi1012\forall i\in[1,n],1\le w_i\le 10^{12}
    • 0k,a,b10180\le k,a,b\le 10^{18} ::::: 容易发现可以先对 {wn}\{w_n\} 排序。
      你考虑怎么把这个东西刻画出来,考虑令 kk 不断增大,以 aa 为横轴,bb 为纵轴建立直角坐标系。
      若后来加入的 wiw_i 较大:

    如图,蓝色等腰三角形部分是 kk 增大前的 (a,b)(a,b) 合法的部分,黄色和红色部分分别是 kk 增大后分别在 xx 和在 yy 中加入 wiw_i 后由原图形平移得到的图形,绿色部分是 kk 增大后新增的 (a,b)(a,b) 合法的部分。容易发现图形扩展后增加了两个平行四边形。

    若后来加入的 wiw_i 很大:

    容易发现此时不会增加图形,且以后均不会增加图形。

    若后来加入的 wiw_i 较小:

    容易发现此时原等腰三角形扩大。

    容易发现当 kk 不断增大时只可能出现上面三种情况,考虑怎么维护这个图形。
    sumksum_k(下标为离散化后的 kk)为图形当 a=0a=0 时合法 bb 的最大值,hkh_k 为当 kk 增大到该值时增加的横轴上的平行四边形的高(若扩大了等腰三角形则就等于 sumksum_k,若什么都没有扩大则就等于 hk1h_{k-1}),sizksiz_k 为目前底部等腰直角三角形的边长,根据上述容易维护出这几个东西的转移。
    每次询问时钦定 aba\ge b,若 (a,b)(a,b) 位于等腰直角三角形内则返回成立,否则我们先找到第一个 sumposa+bsum_{pos}\ge a+bpospos,然后判断 hposh_{pos}bb 的大小关系即可。

    时间复杂度为 Θ(n+qlogn)\Theta(n+q\log n),空间复杂度为 Θ(n)\Theta(n)

    ```cpp
    #include<bits/stdc++.h>
    #define inl inline
    #define int long long
    #define lll __int128
    #define fst ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    #define rep(i,x,y) for(int i=x;i<=(y);++i) 
    #define per(i,x,y) for(int i=x;i>=(y);--i)
    #define rpr(i,x,y,z) for(int i=x;i<=(y);i+=z)
    #define epe(i,x,y,z) for(int i=x;i>=(y);i-=z)
    #define repe(i,x,y) for(i=x;i<=(y);++i) 
    #define pere(i,x,y) for(i=x;i>=(y);--i) 
    #define endl '\n'
    #define INF 2e14
    #define pb push_back
    #define pob pop_back
    #define pf push_front
    #define pof pop_front 
    #define fi first
    #define se second
    #define lcm(x,y) ((x)/__gcd(x,y)*(y))
    #define ull unsigned long long
    #define prr make_pair
    #define pii pair<int,int> 
    #define gt(s) getline(cin,s)
    #define at(x,y) for(auto x:y)
    #define ff fflush(stdout)
    #define mt(x,y) memset(x,y,sizeof(x))
    #define idg isdigit
    #define fp(s) string ssss=s;freopen((ssss+".in").c_str(),"r",stdin);freopen((ssss+\
    ".out").c_str(),"w",stdout);
    #define sstr stringstream 
    #define all(x) x.begin(),x.end()
    #define mcy(a,b) memcpy(a,b,sizeof(b))
    #define ui unsigned
    #define si signed
    #define eb emplace_back
    #define pff(x) ((x)*(x))
    #define eush emplace
    #define double long double
    #define pdi pair<double,int>
    #define gc getchar
    #define pc putchar
    using namespace std;
    const int N=3e5+5;
    int w[N],sum[N],h[N],siz[N];
    inl int lower(int l,int r,int k){
    	int ans=-1;
    	while(l<=r){
    		int mid=l+r>>1;
    		if(sum[mid]>=k){
    			ans=mid;
    			r=mid-1;
    		}else l=mid+1;
    	}
    	return ans;
    }
    inl bool check(int a,int b,int p){
    	if(a<b) swap(a,b);
    	if(a+b<=siz[p]) return 1;
    	int pos=lower(0,p,a+b);
    	if(!~pos) return 0;
    	return h[pos]>=b;
    }
    signed main(){
    //	fp("mio");
    	fst;
    	int n,q,z,v=0;
    	cin>>n>>q;
    	rep(i,1,n) cin>>w[i];
    	sort(w+1,w+n+1);
    	rep(i,1,n){
    		sum[i]=sum[i-1]+w[i];
    		if(w[i]<=(sum[i-1]>>1)+1&&siz[i-1]==h[i-1]) siz[i]=h[i]=sum[i];
    		else if(w[i]<=sum[i-1]+1){
    			siz[i]=siz[i-1];
    			h[i]=min(h[i-1],sum[i-1]+1-w[i]);
    		}else{
                sum[i]=sum[i-1];
                h[i]=h[i-1];
                siz[i]=siz[i-1];
    		}
    	}
    //	rep(i,1,n) cout<<w[i]<<' ';
    //	cout<<endl;
    //	rep(i,1,n) cout<<sum[i]<<' ';
    //	cout<<endl;
    //	rep(i,1,n) cout<<siz[i]<<' ';
    //	cout<<endl;
    //	rep(i,1,n) cout<<h[i]<<' ';
    //	cout<<endl;
    	cin>>z;
    	rep(i,1,q){
    		int k,a,b;
    		cin>>k>>a>>b;
    		k-=z*v;
    		a-=z*v;
    		b-=z*v;
    //		cout<<k<<' '<<a<<' '<<b<<endl;
    		int p=upper_bound(w,w+n+1,k)-w-1;
    		if(check(a,b,p)){
    			cout<<"Yes"<<endl;
    			v+=i;
    		}else cout<<"No"<<endl;
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    7340
    时间
    2000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者