思路:发现a[n-1]>a[n-2]的时候显然不成立。对于成立的情况,我们可以顺其自然的想到逆推:从n开始向数组1扫,观察是否能把数组操作成单调不减的。
#include
using namespace std;
typedef long long ll;
const int N =200010;
ll a[N];
int main(){
int t;
cin>>t;
while(t--){
int n;cin>>n;
ll ans=0;
for(int i=1;i<=n;i++)cin>>a[i];
if(a[n]1]){cout<<-1<<'\n';continue;}
int x=0,y=0,flg=1;
for(int i=n;i>=2;i--){
if(a[i]-a[i-1]<0){flg=0;break;}
if(a[i]-a[i-1]>=0){
if(a[i-1]>=a[i-1]-a[n]){
x=i-1,y=n;break;
}
}
}
if(flg){
if(x==0&&y==0)cout<<0<<'\n';
else {cout<1<<'\n';
for(int i=1;i){
cout<< i<<' '<' '<'\n';
}
}
} else cout<<"-1\n";
}
}
丑代码
D. Infinite Set
一道比较适合你们这帮菜B算法初心者的思维题
题意:给一个n个元素的整数集合,可以把2x+1与4x加入集合中(但数字大小不能超过2^p),求最多可以放多少个数进去
由于p<=2e5,我们自然考虑对它(以及数集中的数)取对数。对于某个数(比如1),假设p=4,我们进行如下观察:
log1=0; log(2+1)=1;log(4*3)=3;
log(4*1)=2; log(4*4)=4(不行,注意题目是取小于号)
log (2*3+1)=2;log(7*2+1)=3;
log(4*2+1)=3;
容易发现这样的数是互异的,并且log要么加一,要么加二。于是题目就变成了斐波那契数列的问题。但我们统计的不是路径数,而是产生的点(换言之,走过的总步数),分别考虑走到取对数后值为n,n-1,n-2……的数有多少个,发现其个数是一个斐波那契前缀和。
最后,注意查重。比如当数集同时存在1和3的时候,由于1可以生成3,所以就不用再次计算3生成的点。
#include
using namespace std;
typedef long long ll;
const int N =200010;
const int mod=1000000007;
ll a[N];
sets;
bool chk(ll i){
while(i){
if(s.find(i)!=s.end())return 0;
if(i%2==1){i=i/2;}
else if(i%4==0){
i=i/4;
}
else return 1;
}
return 1;
}
ll fibbo[200010];
int main(){
ll n,p;
cin>>n>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
}
fibbo[0]=1,fibbo[1]=1;
for(int i=2;i<=200005;i++){
fibbo[i]=(fibbo[i-1]+fibbo[i-2])%mod;
}
for(int i=1;i<=200005;i++){
fibbo[i]=(fibbo[i]+fibbo[i-1])%mod;
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
if(chk(a[i]))s.insert(a[i]);
}
ll ans=0;
for(auto i:s){
ll k= log2(i);
k++;
if(p>=k)ans=(ans+fibbo[p-k])%mod;
}
cout<'\n';
}
应该没有太丑
E. Cars
题意:给出一堆车之间的关系(1——必定不能相遇,2——必定可以相遇),存不存在一条道路上的车,其方向满足这样的关系。
题解:容易发现,无论是关系1还是关系2,两车的方向必定不同。因此可以考虑把题目转换为一个二分图染色问题。
首先考虑奇数个点的环,若存在奇数环就染不来色,寄了
然后考虑对于两车的左右关系连一张DAG,如果DAG走不到头也寄了
如果没寄,就愉快地输出结果吧~
#include
using namespace std;
const int N=200010;
vector<int>mp[N];
int op[3][N];
int in[N],ans[N];
queue<int>q;
char c[2]={'L','R'};
char col[N];
bool dfs(int x,int mod){
if(col[x])return (col[x]==c[mod]);
col[x]=c[mod];mod^=1;
for(auto i:mp[x]){
if(!dfs(i,mod))return 0;
}
return 1;
}
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int n,m;cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>op[0][i]>>op[1][i]>>op[2][i];
mp[op[1][i]].push_back(op[2][i]),mp[op[2][i]].push_back(op[1][i]);
}
for(int i=1;i<=n;i++){
if(!col[i]){
if(!dfs(i,0)){cout<<"NO"<<'\n';return 0;}
}
}
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=1;i<=m;i++){
if(op[0][i]==1&&col[op[1][i]]=='L')mp[op[1][i]].push_back(op[2][i]),in[op[2][i]]++;
if(op[0][i]==1&&col[op[1][i]]=='R')mp[op[2][i]].push_back(op[1][i]),in[op[1][i]]++;
if(op[0][i]==2&&col[op[1][i]]=='R')mp[op[1][i]].push_back(op[2][i]),in[op[2][i]]++;
if(op[0][i]==2&&col[op[1][i]]=='L')mp[op[2][i]].push_back(op[1][i]),in[op[1][i]]++;
}
for(int i=1;i<=n;i++)if(!in[i])q.push(i);
int tot=0;
while(!q.empty()){
int f=q.front();q.pop();ans[f]=++tot;
for(auto i:mp[f]){in[i]--;if(!in[i])q.push(i);}
}if(tot"NO\n";return 0;}
cout<<"YES\n";
for(int i=1;i<=n;i++){
cout<' '<'\n';
}
}
不丑的代码!
F. Closest Pair
题意 :每个点有坐标和重量,一条线段的权值是距离乘端点质量之和。离线询问,每次询问给出l和r,找权值最小的区间。
题解:若某对点对权值最小,它们中间不能存在比质量比两点更小的数。于是可以考虑单调栈把这样的点对预处理出来,由于每个数最多进出栈一次,所以这样的点对是On的。
于是变成了一个我第一次做的二维数点问题。
#include
using namespace std;
typedef long long ll;
const int N=300010;
ll w[N],l[N],ans[N];
ll tr[N];
vectorint,ll>>pr[N],q[N];
int n;
void add(int x,ll y){
for(;x<=n;x+=x&-x)tr[x]=min(tr[x],y);
}
ll qry(int x){
ll res=LLONG_MAX;
for(;x;x-=x&-x)res=min(res,tr[x]);
return res;
}
int main(){cin.tie(0);ios::sync_with_stdio(0);cout.tie(0);
int Q;cin>>n>>Q;
stack<int>s;
fill(tr,tr+n+3,LLONG_MAX);
for(int i=1;i<=n;i++){
cin>>l[i]>>w[i];
while(!s.empty()&&w[i]<w[s.top()]){
pr[i].push_back({s.top(),(l[i]-l[s.top()])*(w[s.top()]+w[i])});
s.pop();
}
if(!s.empty()){
pr[i].push_back({s.top(),(l[i]-l[s.top()])*(w[s.top()]+w[i])});
}
s.push(i);
}
for(int i=1;i<=Q;i++){
int x,y;cin>>x>>y;
q[y].push_back({x,i});
}
for(int i=1;i<=n;i++){
for(auto x:pr[i]){
add(n+1-x.first,x.second);
}
for(auto x:q[i]){
ans[x.second]= qry(n+1-x.first);
}
}
for(int i=1;i<=Q;i++){
cout<'\n';
}
}
部分代码参考了DLS