1 条题解
-
0
:::::info[闲话] 神秘组合刻画题。
::::: :::::info[题目基本信息] 考察:Ad-hoc(省选/NOI-)。
题目简介:
给定 个物品,每个物品有权值,权值构成序列 。 次询问,每次询问给定 ,假想有两个初始为 的数 ,对于所有 的物品,你可以选择令 ,也可以选择令 ,也可以不操作。最终问对于所有 , 是否都能通过操作变成 。
强制在线。
数据范围:-
:::::
容易发现可以先对 排序。
你考虑怎么把这个东西刻画出来,考虑令 不断增大,以 为横轴, 为纵轴建立直角坐标系。
若后来加入的 较大:

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

容易发现此时不会增加图形,且以后均不会增加图形。
若后来加入的 较小:

容易发现此时原等腰三角形扩大。
容易发现当 不断增大时只可能出现上面三种情况,考虑怎么维护这个图形。
设 (下标为离散化后的 )为图形当 时合法 的最大值, 为当 增大到该值时增加的横轴上的平行四边形的高(若扩大了等腰三角形则就等于 ,若什么都没有扩大则就等于 ), 为目前底部等腰直角三角形的边长,根据上述容易维护出这几个东西的转移。
每次询问时钦定 ,若 位于等腰直角三角形内则返回成立,否则我们先找到第一个 的 ,然后判断 和 的大小关系即可。时间复杂度为 ,空间复杂度为 。
```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
- 上传者