可以把图形镜像翻转一下,如果两个图形是完全一样,那么就一定是对称的,翻转过来后发现长变成了宽,利用差分重构一下翻转后的图形,再和原图形判断是否完全相同
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
template<typename T>
T rmin(T &a,T b){if(a>b)a=b;return a;}
template<typename T>
T rmax(T &a,T b){if(a<b)a=b;return a;}
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=1e9+7;
string s;
int n,m,k;
int a[N],b[N];
void solve(){
cin>>n;
fr(1,i,n)cin>>a[i];
if(a[1]>n){
cout<<NO<<endl;
return ;
}
fr(1,i,n+1)b[i]=0;
b[1]=n;
fr(1,i,n){
b[a[i]+1]--;
}
fr(1,i,n)b[i]+=b[i-1];
// fr(1,i,n)cout<<b[i]<<' ';cout<<endl;
fr(1,i,n){
if(a[i]!=b[i]){
cout<<NO<<endl;
return ;
}
}
cout<<YES<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
fr(1,i,t){
solve();
}
}
如果总共有n个球,那么最多可以有n*(n-1)/2+n种配合,后面的+n是可以改变的,同时计算一下n个球和n-1个球的差距是小于n的,所以可以通过二分计算最少需要多少球才能让n*(n-1)/2+x(0<=x<=n)满足题目要求的个数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
template<typename T>
T rmin(T &a,T b){if(a>b)a=b;return a;}
template<typename T>
T rmax(T &a,T b){if(a<b)a=b;return a;}
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=1e9+7;
string s;
int n,m,k;
int a[N];
ll check(ll x){
return (x*(x-1))/2;
}
void solve(){
ll n;
cin>>n;
ll mi=0,mx=2648956421;
while(mi<=mx){
ll mid=(mi+mx)>>1;
if(check(mid)>n){
mx=mid-1;
}else{
mi=mid+1;
}
}
ll ans=mi-1;
cout<<ans+(n-check(ans))<<endl;
// cout<<ans<<' '<<n-check(ans)<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
fr(1,i,t){
solve();
}
}
这个题目首先要转换一下思维,假设你最后一个位置选在i,那么一定会有i*d的损失,这个损失是固定的,所以我们可以枚举最右端,使用优先队列维护我们拿到的m个最大值.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
template<typename T>
T rmin(T &a,T b){if(a>b)a=b;return a;}
template<typename T>
T rmax(T &a,T b){if(a<b)a=b;return a;}
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=1e9+7;
string s;
ll n,m,k;
int a[N];
void solve(){
cin>>n>>m>>k;
fr(1,i,n)cin>>a[i];
priority_queue<int,vector<int>,greater<int>>que;
ll ans=0,sum=0;
fr(1,i,n){
if(a[i]<0)continue;
if(que.size()<m)que.push(a[i]),sum+=a[i];
else{
if(que.top()<a[i]){
sum-=que.top();que.pop();
sum+=a[i];
que.push(a[i]);
}
}
ans=max(ans,sum-i*k);
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
fr(1,i,t){
solve();
}
}
二分+背包
水和火的蓝条每一秒固定增长的,所以我们直接二分时间,然后通过背包判断是否能将所有的怪物杀死
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
template<typename T>
T rmin(T &a,T b){if(a>b)a=b;return a;}
template<typename T>
T rmax(T &a,T b){if(a<b)a=b;return a;}
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=1e9+7;
string s;
int n,m,k;
int a[N];
ll w,f;
bitset<M>bt;
int check(int t){
ll tw=w*t,tf=f*t;
ll sum=0;
bt.reset();
bt[0]=1;
fr(1,i,n){
sum+=a[i];
bt|=(bt<<a[i]);
}
if(tw>=sum||tf>=sum)return 1;
int mx=0;
fe(0,i,tw){
if(bt[i]){
mx=i;
break;
}
}
if(tf>=sum-mx)return 1;
return 0;
}
void solve(){
cin>>w>>f;
cin>>n;
fr(1,i,n)cin>>a[i];
int l=0,r=M;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)){
r=mid-1;
}else{
l=mid+1;
}
}
cout<<l<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
fr(1,i,t){
solve();
}
}
题目的结论不太难猜,主要是代码写的很痛苦
观察就可以发现,最终的答案就是对于当前的数组element_max-element_min(最大值减去最小值)再加上相邻两个数差值的最大值.
需要一直维护相邻两个数的差值,重点写好add和del函数,这个题就很简单了.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define all(a) a.begin(),a.end()
#define fr(a,i,n) for(int i=a;i<=n;i++)
#define fe(a,i,n) for(int i=n;i>=a;i--)
#define fcf(i,cur) for(int i=cfs.h[cur],sup=cfs.e[i];i;i=cfs.net[i],sup=cfs.e[i])
#define endl "\n"
istream &operator>>(istream &in,pii &a){return in>>a.first>>a.second;};
ostream &operator<<(ostream&,pii &a){return cout<<a.first<<' '<<a.second;};
template<typename T>
istream &operator>>(istream &in,vector<T>&v){T x;in>>x;v.push_back(x);return in;};
template<typename T>
T rmin(T &a,T b){if(a>b)a=b;return a;}
template<typename T>
T rmax(T &a,T b){if(a<b)a=b;return a;}
string YES="YES",Yes="Yes",yes="yes",NO="NO",No="No",no="no";
const int N=2e5+10,M=1e6+10,mod=1e9+7;
string s;
int n,m,k;
int a[N];
map<int,int>ar1,ar2,cnt;
void add(int x){
ar1[x]++;
ar2[-x]++;
if(ar1[x]>1){
return ;
}
int a=0,c=0;
if(ar1.upper_bound(x)!=ar1.end())c=ar1.upper_bound(x)->first;
if(ar2.upper_bound(-x)!=ar2.end())a=-(ar2.upper_bound(-x)->first);
if(a)cnt[x-a]++;
if(c)cnt[c-x]++;
if(a&&c)if(--cnt[c-a]==0)cnt.erase(c-a);
}
void del(int x){
ar1[x]--;ar2[-x]--;
if(ar1[x])return ;
ar1.erase(x);
ar2.erase(-x);
int a=0,c=0;
if(ar1.upper_bound(x)!=ar1.end())c=ar1.upper_bound(x)->first;
if(ar2.upper_bound(-x)!=ar2.end())a=-(ar2.upper_bound(-x)->first);
if(a)if(--cnt[x-a]==0)cnt.erase(x-a);
if(c)if(--cnt[c-x]==0)cnt.erase(c-x);
if(a&&c)cnt[c-a]++;
}
void solve(){
cin>>n;
ar1.clear();ar2.clear();cnt.clear();
fr(1,i,n)cin>>a[i];
fr(1,i,n)add(a[i]);
int q;
cin>>q;
int i,x;
while(q--){
cin>>i>>x;
del(a[i]);
a[i]=x;
add(a[i]);
if(cnt.empty())cout<<ar1.rbegin()->first<<' ';
else
cout<<ar1.rbegin()->first+cnt.rbegin()->first<<' ';
}
cout<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
fr(1,i,t){
solve();
}
}