A.dd爱科学1.0
思路:求最长上升子序列,因为这里的范围是1e6,所以直接用dp,时间复杂度是O(n*n),会超时,所以要进行优化,因为上升子序列中是单调上升的,所以我们可以通过二分来找到比当前数小的最大的数,由此找到最大长度。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int a[maxn],f[maxn];
string s;
int main()
{
int n;
cin>>n;
cin>>s;
for(int i=0;i<s.length();i++)
{
a[i]=s[i]-'A'+1;
}
int len=0;
f[0]=0;
for(int i=0;i<n;i++)
{
int l=0,r=len;
while(l<r)
{
int mid=l+r+1>>1;
if(f[mid]<=a[i])//注意这里不是严格单调上升的,可以等于
{
l=mid;
}
else
{
r=mid-1;
}
}
len=max(len,r+1);
f[r+1]=a[i];
}
cout<<n-len;
return 0;
}
思路:
对于顺时针旋转180度,如果是偶数次,就相当于没有变。如果是奇数次,我们只需要按一次计算就行了。
同理,对于行镜像也是一样。
(不过要注意一点,旋转的时候要用新的数组存否则会覆盖)
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS \
ios::sync_with_stdio(false);\
cin.tie(0)
// *start on @date: 2021-10-17 18:53
int a[1010][1010],ans[1010][1010],flag=0;
int main()
{
IOS;
int q,k,n,count1=0,count2=0;
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>a[i][j];
ans[i][j]=a[i][j];
}
}
cin>>q;
for(int i=0;i<q;i++)
{
cin>>k;
if(k==1)
{
count1++;
}
else
{
count2++;
}
}
if(count1%2==1)//顺时针旋转180度
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
ans[i][j]=a[n-i-1][n-j-1];
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
a[i][j]=ans[i][j];
}
}
}
if(count2%2==1)//行镜像
{
for(int i=0;i<n/2;i++)
{
for(int j=0;j<n;j++)
{
swap(a[i][j],a[n-i-1][j]);
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
F.dd爱框框
思路:
前缀和
从前往后加,找到第一个大于x的r,然后从前往后找到大于x的最小值,就是r,然后继续往后,得到最小区间,因为是从前往后所以l一定是最小的。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[10000010],l=0,r=0,sum=0,j=1,minn=INT_MAX;
int main()
{
int n,x;
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
while(sum>=x)
{
if(i-j<minn)
{
minn=i-j;
l=j;
r=i;
}
sum-=a[j++];
}
}
cout<<l<<" "<<r<<endl;
return 0;
}