队列及其应用
理性查看,提升自己
问题 K: 连贯子序列
抗病在线,终于搞定了,时间复杂度n^2不让过,优化了半天,终于利用map在nlog下完成了。
我还是太菜了,想不出二分或者队列的方法,dp也不行。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=2e5+10,INF=0x3f3f3f3f;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int a[200010],vis[200010];
void bu_f(){
int n=read();
int id=1;int len=1;
map<int,int> ma;//umap又快了一倍
for(int i=1;i<=n;i++){
a[i]=read();
ma[a[i]]=1;
if(ma[a[i]-1]) {
ma[a[i]]+=ma[a[i]-1];//如果刚好小于1值前面出现,就加上他的贡献
if(ma[a[i]]>len){//更新
len=ma[a[i]];
id=i;
}
}
}
cout<<len<<'\n';
cout<<id;
}
int main(){
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
// int t=read();
int t=1;
while(t--){
bu_f();
}
return 0;
}
接下来就势如破竹吧
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=2e5+10,INF=0x3f3f3f3f;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
void bu_f(){
int n=read();
vector<int> a(n);
for(int &v:a) v=read();
sort(a.begin(),a.end());
int len=0;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++){
auto it=lower_bound(a.begin()+j+1,a.begin()+n,-(a[j]+a[i]));
if(it!=a.end()&&*it==-(a[j]+a[i])){
len++;
}
}
if(len) cout<<len;
else cout<<"No Solution。";
}
int main(){
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
// int t=read();
int t=1;
while(t--){
bu_f();
}
return 0;
}
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=2e5+10,INF=0x3f3f3f3f;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
void bu_f(){
int n=read();
vector<int> a(n+1);
map<int,int> ma;
for(int i=1;i<=n;i++) a[i]=read(),ma[a[i]]=1;
sort(a.begin()+1,a.end(),[](int x,int y){
return abs(x)<abs(y);
});
int k=read();
// vector<int> b(k+1);
for(int i=1;i<=k;i++) {
int b=read();
if(!ma.count(b)) {
cout<<-1<<'\n';
continue;
}
for(int j=1;j<=n;j++){
if(b==a[j]){
cout<<j<<'\n';
break;
}
}
}
}
int main(){
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
// int t=read();
int t=1;
while(t--){
bu_f();
}
return 0;
}
问题 N: 正整数分组
很典的题
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=1e4+10,INF=0x3f3f3f3f;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int a[N];
int n,k;
bool check(LL x){
int len=1,sum=0;
for(int i=1;i<=n;i++){
if(sum+a[i]>x){
len++;
sum=a[i];
}
else sum+=a[i];
}
return len<=k;
}
void bu_f(){
n=read(),k=read();
for(int i=1;i<=n;i++) a[i]=read();
LL l=0,r=1e15+10;
while(l+1<r){
LL mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid;
}
cout<<r;
}
int main(){
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
// int t=read();
int t=1;
while(t--){
bu_f();
}
return 0;
}
问题 O: 计算平均值最大子段
这边卡了一波
ans<sum/k,可以更新,转化ansk<sum
sum是k个a[i]相加
接着转化
k(a[i]-ans)>0
k个a[i]-ans可以利用前缀和求得,关键是k不知道
可以利用前缀和pre[r]-pre[l],保证r-l>=m
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=1e5+10,INF=0x3f3f3f3f;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
double a[N],b[N],pre[N];
int n,L;
LL sum=0;
bool check(double x){
double min_left=1e10; //min_left:最小前缀和
for (int i=1;i<=n;i++) b[i]=a[i]-x;
for (int i=1;i<=n;i++) pre[i]=pre[i-1]+b[i];//pre[]:前缀和数组
for (int r=L;r<=n;r++) //一个小贪心,从L开始枚举右端点
{
min_left=min(min_left,pre[r-L]);//不断更新符合条件的最小前缀和
if (pre[r]-min_left>=0) return true;
}
return false;
}
void bu_f(){
n=read(),L=read();
for(int i=1;i<=n;i++) a[i]=read();
double l=0,r=1e6,d=1e-5;
while(r-l>d){
double mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
cout<<(int)(1000*r);
}
int main(){
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
// int t=read();
int t=1;
while(t--){
bu_f();
}
return 0;
}
问题 P: 中位数(完善程序)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=1000,INF=0x3f3f3f3f;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int n,i,lbound,rbound,mid,m,count;
int x[N];
void bu_f(){
n=read(),m=read();
for(int i=0;i<n;i++) x[i]=read();
sort(x,x+n);
cout<<x[n/2];
}
int main(){
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
// int t=read();
int t=1;
while(t--){
bu_f();
}
return 0;
}
问题 Q: 切割绳子(程序填空)
点击查看代码
#include <iostream>
using namespace std;
int n, m, i,l,r, mid, count,sum;
int len[150]; // 绳子长度
bool check(int x){
count=0;
for(int i=1;i<=n;i++){
count+=len[i]/x;
}
return count>=m;
}
int main()
{
cin >> n;
count = 0;
for (i = 1; i <= n; i++)
{
cin >> len[i];
sum+=len[i];
}
cin >> m;
if(sum<m)
{
cout << "Failed" <<endl;
return 0;
}
l=0,r=1000000+1;
while (l+1<r)
{
mid = l+r>>1;
if(check(mid)) l=mid;
else r=mid;
}
cout << l << endl;
return 0;
}
浙公网安备 33010602011771号