cf736D
思路:a%m=n同时b%m=n,c%m=n(m>=2)可以推出gcd(a-b,b-c)!=1
可以直接双指针来做,不过可能代码会写出锅
由于数组是静态的不会变化,可以考虑使用st表来维护
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10;
ll c[N], a[N];
ll f[N][65];
int t, n;
void init(int n)
{
for (int i = 1; i <= n; i++)
f[i][0] = a[i];
for (int j = 1; j < log(n) / log(2) + 1; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
f[i][j] = __gcd(f[i][j - 1], f[i + (1ll << (j - 1))][j - 1]);
}
}
ll query(int l, int r)
{
int len = r - l + 1;
int k = log(len) / log(2);
return __gcd(f[l][k], f[r - (1 << k) + 1][k]);
}
int main()
{
cin >> t;
while (t--)
{
cin >> n;
for (int i = 1; i <= n; i++)
a[i] = c[i] = 0;
for (int i = 0; i <= n; i++)
for (int j = 0; j < 65; j++)
f[i][j] = 0;
for (int i = 1; i <= n; i++)
{
cin >> c[i];
}
for (int i = 1; i < n; i++)
a[i] = abs(c[i + 1] - c[i]);
init(n - 1);
int ans = 1;
for (int i = 1, j = 1; i <= n - 1; i++)
{
while (j <= i && query(j, i) == 1)
j++;
ans = max(ans, i - j + 2);
}
cout << ans << endl;
}
return 0;
}
cf629D
思路:
从题意中可以读出来,这题让求得是最大上升子序列和,由于我太菜了只会写O(N^2)的丑陋代码,显然tle,然后换了个思路来想,当走到第i个得时候,我们只需要考率i前边比i小的集合里边的最大值,然后就可以转化为前缀区间最大值,可以使用树状数组来维护,注意不要从0开始
由于最后放的时候两个相邻的蛋糕不能一样大,就不需要离散化,只需要排序,去重就ok
代码:
#include<bits/stdc++.h>
#define ll long long
#define pi 3.141592654
using namespace std;
const int N=1e5+10;
ll p[N],c[N],d[N];
int cnt;
int n;
int lowbit(int x)
{
return x&-x;
}
ll query(int x)
{
ll res=0;
while(x)
{
res=max(res,p[x]);
x-=lowbit(x);
}
return res;
}
void add(int x,ll val)
{
while(x<=cnt)
{
p[x]=max(p[x],val);
x+=lowbit(x);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
ll a,b;
cin>>a>>b;
c[i]=d[i]=a*a*b;
}
sort(c+1,c+n+1);
cnt=unique(c+1,c+n+1)-c;
ll ans=0;
for(int i=1;i<=n;i++)
{
int l=1,r=cnt;
while(l<r)
{
int mid=l+r>>1;
if(c[mid]>d[i]) r=mid;
else l=mid+1;
}
ll res=query(l-1)+d[i];
ans=max(ans,res);
add(l,res);
}
printf("%.6lf\n",double(ans)*pi);
return 0;
}