20200525日常摸鱼
共计8题,有点少
今日训练时长:未定
洛谷P1638 逛画展
先从1开始读入数据,直到画家数量达到m的时候,便可以开始真正的处理,首先设置左端点l=1,右端点r=第一次满画家的位置,同时b数组用来存储这一段画家各出现了多少次,桶排的思想,然后判断左端点的点出现次数是否>1,假如大于1的话就可以删去,直到左端点无法再删除,这时比较下l,r和q,w,取最短的区间保存,然后每次r++,都重复进行上面的操作,判断左端点能否删,并取最短区间,这题就做完了
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
typedef vector<int> VI;
const ll mod=1000000007;
const int maxn=1000005;
const int inf=0x3f3f3f3f;
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
// head
set<int> s1;
int a[maxn];
int b[maxn];
int n,m;
int main()
{
cin>>n>>m;
rep(i,1,n+1)
{
cin>>a[i];
}
int l=1,r=0;
int q=1,w=0;
while(r<n)
{
s1.insert(a[++r]);
b[a[r]]++;
if(s1.size()==m)
break;
}
while(b[a[l]]>1)
{
b[a[l]]--;
l++;
}
q=l,w=r;
while(r<n)
{
b[a[++r]]++;
while(b[a[l]]>1)
{
b[a[l]]--;
l++;
}
if(r-l<w-q)
{
q=l,w=r;
}
}
cout<<q<<" "<<w<<"\n";
return 0;
}
P1714 切蛋糕
第一眼,找连续的区间,长度为k,最大值,甚至不是环形,这不是傻逼题吗,
然后写了个这个
rep(i,1,n+1)
{
b[i]+=b[i-1]+a[i];
if(i>=m)
{
maxx=max(maxx,b[i]-b[i-m]);
}
}
然后发现样例二都过不去,才发现是区间长度<=k都可,又改成了这样
rep(i,1,n+1)
{
b[i]+=b[i-1]+a[i];
if(i>=m)
{
for(int j=i-m;j<i;j++)
maxx=max(maxx,b[i]-b[j]);
}
}
再一想,这复杂度炸了,那么咋优化呢,哦对,这不就是长度为k的区间,找到一个最小值吗?单调队列呀(滑动窗口),然后去找了下我的单调队列模板(555,我忘了咋写了),然后就过了,哦对,以及因为我是用前缀和处理的,所以m需要+1,才能减到最远的那个数字
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
typedef vector<int> VI;
const ll mod=1000000007;
const int maxn=500005;
const int inf=0x3f3f3f3f;
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
#define ms(a) memset(a,0,sizeof(a))
#define mss(a) memset(a,-1,sizeof(a))
#define msi(a) memset(a,inf,sizeof(a))
#define iossync ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// head
int n,m;
ll a[maxn];
ll b[maxn];
ll loc[maxn];
ll maxx=0;
int main()
{
iossync
cin>>n>>m;
rep(i,1,n+1)
{
cin>>a[i];
}
rep(i,1,n+1)
{
b[i]+=b[i-1]+a[i];
// if(i>=m)
// {
// for(int j=i-m;j<i;j++)
// maxx=max(maxx,b[i]-b[j]);
// }
}
int head=1,tail=1;
loc[head]=1;
m++;
rep(i,1,n+1)
{
if(loc[head]<=i-m)
{
head++;
}
while(tail>=head && b[loc[tail]]>=b[i])
tail--;
loc[++tail]=i;
if(i>=m)
{
maxx=max(maxx,b[i]-b[loc[head]]);
}
}
cout<<maxx<<"\n";
return 0;
}
P3865 【模板】ST表
ST表模板题,我跟着oiwiki学的,套一下模板过去了,以及这题读入的数据非常恐怖,强制快读,5555
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
const int maxn=100005;
const int LOG=21;//2*10^9
int f[maxn][LOG];
int logn[maxn];
int n,m,l,r;
void init()
{
logn[1]=0;
logn[2]=1;
rep(i,3,maxn)
{
logn[i]=logn[i/2]+1;
}
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// cin>>n>>m;
// scanf("%d %d",&n,&m);
n=read(),m=read();
rep(i,1,n+1)
{
// cin>>f[i][0];
// scanf("%d",&f[i][0]);
f[i][0]=read();
}
init();//预处理log,防止太慢了
// rep(i,0,LOG)//10^9
rep(j,1,LOG)
{
// rep(j,1,n-(1<<j)+1+1)
rep(i,1,n-(1<<j)+1+1)
//原型//for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
f[i][j]=max(f[i][j-1] ,f[i+(1<<(j-1))][j-1]);
}
}
rep(i,0,m)
{
// cin>>l>>r;
// scanf("%d %d",&l,&r);
l=read(),r=read();
int s=logn[r-l+1];//区间长度
// cout<<max(f[l][s],f[r-(1<<s)+1][s])<<"\n";
printf("%d\n",max(f[l][s],f[r-(1<<s)+1][s]));
}
return 0;
}
//
P1816 忠诚
emmm,其实,跟上面那题,只要把max改成min,就好了,话说加个#define max min是不是就行
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
const int maxn=100005;
const int LOG=21;//2*10^9
int f[maxn][LOG];
int logn[maxn];
int n,m,l,r;
void init()
{
logn[0]=0;
logn[1]=0;
logn[2]=1;
rep(i,3,maxn)
{
logn[i]=logn[i/2]+1;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
rep(i,1,n+1)
cin>>f[i][0];
init();
rep(j,1,LOG)
{
rep(i,1,n-(1<<j)+2)
{
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
rep(i,0,m)
{
cin>>l>>r;
int s=logn[r-l+1];
cout<<min(f[l][s],f[r-(1<<s)+1][s])<<" ";
}
return 0;
}
P1138 第k小整数
学会了unique,把没出现过的数字往前提, 这个网站写的就很详细unique用法
以及这题也可用unique传送门
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
typedef vector<int> VI;
const ll mod=1000000007;
const int maxn=100005;
const int inf=0x3f3f3f3f;
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
#define ms(a) memset(a,0,sizeof(a))
#define mss(a) memset(a,-1,sizeof(a))
#define msi(a) memset(a,inf,sizeof(a))
#define iossync ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// head
int n,k;
int a[maxn];
int main()
{
cin>>n>>k;
rep(i,0,n)
{
cin>>a[i];
}
sort(a,a+n);
int ans=unique(a,a+n)-a;
if(ans>=k)
{
cout<<a[k-1];
}
else
cout<<"NO RESULT\n";
return 0;
}
P1102 A-B 数对
题解很多是用map和hash写的,emmmm,说实话我都没想到,用的sort和lower_bound与upper_bound
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
const int maxn=200005;
typedef long long ll;
ll a[maxn];
ll n,c,sum;
int main()
{
cin>>n>>c;
rep(i,0,n)
{
cin>>a[i];
}
sort(a,a+n);
rep(i,0,n)
{
ll qwe=upper_bound(a,a+n,a[i]+c)-lower_bound(a,a+n,a[i]+c);
ll asd=upper_bound(a,a+n,a[i])-a-i;
// sum+=upper_bound(a,a+n,a[i]+c)-lower_bound(a,a+n,a[i]+c);
sum+=asd*qwe;
i=upper_bound(a,a+n,a[i])-a-1;
}
cout<<sum<<"\n";
return 0;
}
P1419 寻找段落
二分平均值,前缀和处理,每次判断能否匹配,同时加入单调队列优化处理
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
typedef vector<int> VI;
const ll mod=1000000007;
const int maxn=100005;
const int inf=0x3f3f3f3f;
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
#define ms(a) memset(a,0,sizeof(a))
#define mss(a) memset(a,-1,sizeof(a))
#define msi(a) memset(a,inf,sizeof(a))
#define iossync ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// head
int a[maxn];
db b[maxn];
int n,s,t;
int loc[maxn];
bool check(double x)
{
// ms(b,0,sizeof(b)
rep(i,1,n+1)
{
b[i]=b[i-1]+a[i]-x;
}
int head=0,tail=0;
loc[head]=1;
rep(i,s,n+1)
{
if(loc[head]<i-t)
head++;
while(tail>=head && b[loc[tail]]>b[i-s])
tail--;
loc[++tail]=i-s;
if(b[i]-b[loc[head]]>=0)
return 1;
}
return 0;
}
int main()
{
cin>>n>>s>>t;
rep(i,1,n+1)
cin>>a[i];
double l=-10000,r=10000,mid;
while(r-l>0.000001)
{
mid=(l+r)/2;
if(check(mid))
l=mid;
else
r=mid;
}
// cout<<l<<"\n";
printf("%.3lf\n",l);
return 0;
}
P3124 [USACO15OPEN]Trapped in the Haybales S
这题的输入简直有病,先介绍距离和大小,结果先输入大小,再输入距离,以及翻译有点小瑕疵
直接把我卡死
简单就是分左右边,先sort一下,然后找到左边第一个不可能突破的点,然后找右边最小加固的,然后再找到右边第一个不可能突破的点,然后找左边最小加固的,两遍循环
#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
typedef long long ll;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
const int inf=0x3f3f3f3f;
ll b[maxn],n,m,r,l;
pair<ll,ll> a[maxn];
int main()
{
cin>>n>>m;
rep(i,0,n)
{
cin>>a[i].second>>a[i].first;
a[i].first-=m;
}
sort(a,a+n);
int flag=-1;
rep(i,0,n-1)
{
if(a[i].first<0 && a[i+1].first>0)
{
flag=i;
break;
}
}
if(flag==-1)
{
cout<<"-1\n";
return 0;
}
ll ans=9999999999999;
ll asd=ans;
r=flag+1;
for(int i=flag;i>=0;i--)
{
while(r<n && a[r].first-a[i].first>a[r].second)
{
r++;
}
if(r>=n)
break;
ans=min(ans,a[r].first-a[i].first-a[i].second);
}
l=flag;
for(int i=flag+1;i<n;i++)
{
while(l>=0 && a[i].first-a[l].first>a[l].second)
{
l--;
}
if(l<0)
break;
ans=min(ans,a[i].first-a[l].first-a[i].second);
}
// per(i,0,flag+1)
// {
// rep(j,flag+1,n)
// {
// if(a[i].second>=a[j].first-a[i].first+1)
// {
// if(a[j].second>=a[j].first-a[i].first+1)
// {
// ans=b[i]=0;
// break;
// }
// }
// else
// {
// b[i]=a[j].first-a[i].first+1-a[i].second;
// ans=min(b[i],ans);
// break;
// }
// }
// if(ans==0)
// break;
// }
if(ans==asd)
cout<<"-1\n";
else
cout<<max(ans,0ll)<<"\n";
return 0;
}