F - Permutation
水题,岔开构造就行
H - A Simple Stone Game
这样考虑:如果一个结果得gcd是x,那么这个x肯定是所有石子和的某个因子,所以遍历所有因子,取模之后模拟就行了
B - K-th Number
将每个大于K的区间的第K大都求出来放到新的数组里面,然后求出新的数组中的第M大。
首先真的求出来所有的区间的第K大是不现实的,也就是说我们要二分一下,我们二分最后的第M大的数,对于这个数,他作为区间的第K大的次数如果大于M,说明我们要增大,反之这个数还可以增大。
如何求出来有多少个区间呢?我们首先已经固定了目前判断的数,那么我们使用尺取,先找到正好满足第K大的区间(K个大于mid的数),这个区间可以往后也就是[r,n] 取到的K大值一定都是大于等于mid的,所以把这一段先加上去,对于每个当前区间小于mid的值,都会使区间的个数增加一次。
#include <bits/stdc++.h>
#define ll long long
#define find fuck
#define next fuckme
using namespace std;
const int MAXN = 1e5 + 5;
int a[MAXN];
int n,k;
ll m;
bool check(int mid)
{
ll ans = 0;
int num = 0;
int j = 1;
for(int i = 1;i<=n;i++)
{
if(a[i] >= mid) num++;
if(num == k)
{
ans += n - i + 1;
while(a[j] < mid)
{
ans += n - i + 1;
j++;
}
num--;
j++;
}
}
return ans >= m;
}
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
scanf("%d%d%lld",&n,&k,&m);
for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
int l = 1,r = 1e9 + 7;
while(l < r)
{
int mid = (l + r) >> 1;
if(check(mid))
{
l = mid+1;
}
else r = mid;
}
printf("%d\n",l-1);
}
return 0;
}
A - Palindrome
我靠这题这么些系列……
题意是找到形如 ()i () j () 这样的回文串。也就是以i为中心和以j为中心都是回文的。
我们设p[i]为i位置上的回文半径,我们观察一下这个回文串,可以得出三个关系
i
<
j
,
i
≥
j
−
p
j
,
j
≤
i
+
p
i
i < j , i \ge j - p_j ,j \le i +p_i
i<j,i≥j−pj,j≤i+pi
有了这个,我们可以用树状数组维护这个数组,我们先把所有i - p_i 的位置存起来,然后在查询第i个位置的时候,也就是满足第以个式子的值,把这个位置对应的位置都存入树状数组,这样我们就求出来一堆符合的位置,然后我们要满足第一个式子,就查询满足式子1,3的i ~ i + p[i] 这一段的值
#include <bits/stdc++.h>
#define ll long long
#define find fuck
#define next fuckme
using namespace std;
const int MAXN=5e5 + 10;
char Ma[MAXN*2];
int Mp[MAXN*2];
int Manacher(char s[],int len)
{
int l=0;
Ma[l++]='$';
Ma[l++]='#';
for(int i=0; i<len; i++)
{
Ma[l++]=s[i];
Ma[l++]='#';
}
Ma[l]=0;
int mx=0,id=0;
for(int i=0; i<l; i++)
{
Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;
while(Ma[i+Mp[i]]==Ma[i-Mp[i]])
Mp[i]++;
if(i+Mp[i]>mx)
{
mx=i+Mp[i];
id=i;
}
}
return l;
}
char s[MAXN];
int bit[MAXN],p[MAXN];
vector<int> g[MAXN];
inline int lowbit(int x)
{
return x & (-x);
}
int MX;
int sum(int i)
{
int s = 0;
while(i>0){
s += bit[i];
i -= i & -i;
}
return s;
}
void add(int i, int x)//i 不能取 0
{
while(i<=MX){
bit[i] += x;
i += i&-i;
}
}
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
memset(bit,0,sizeof(bit));
for(int i = 0;i<MAXN;i++) g[i].clear();
scanf("%s",s);
int slen = strlen(s);
int len = Manacher(s,slen);
int k = 1;
for(int i = 2;i<len;i+=2)
{
p[k] = Mp[i]/2-1;
g[k - p[k]].push_back(k);
k++;
}
// for(int i = 1;i<=k;i++)
// cout<<p[i]<<' ';
// cout<<endl;
MX = slen;
ll ans = 0;
for(int i = 1;i<=slen;i++)
{
for(int j = 0;j<(int)g[i].size();j++)
{
add(g[i][j],1);
}
ans += sum(min(i + p[i],slen)) - sum(i);
}
printf("%I64d\n",ans);
}
return 0;
}
M - Geometry Problem
啥话不说了,直接随机,但是n小于4的时候要特殊处理一下,因为很可能判断到三点共线的情况
#include <bits/stdc++.h>
#define ll long long
#define find fuck
#define next fuckme
using namespace std;
const int MAXN = 1e5 + 5;
const double eps = 1e-6;
struct Point
{
double x,y;
Point() {};
Point(double _x,double _y)
{
x = _x,y = _y;
}
Point operator - (const Point &b) const
{
return Point(x - b.x,y- b.y);
}
double operator * (const Point &b) const
{
return x*b.x + y*b.y;
}
};
Point p[MAXN];
Point get_circle(Point a,Point b,Point c)
{
double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1*a1 + b1*b1)/2;
double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2*a2 + b2*b2)/2;
double d = a1*b2 - a2*b1;
return Point(a.x + (c1*b2 - c2*b1)/d, a.y + (a1*c2 -a2*c1)/d);
}
double dist(Point a,Point b)
{
return sqrt((a- b)*(a - b));
}
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
int n,k;
scanf("%d",&n);
k = (n +1)/2;
for(int i = 0; i<n; i++)
{
double x,y;
scanf("%lf%lf",&x,&y);
p[i] = Point(x,y);
}
if(n == 1)
{
printf("%.12f\n %.12f 0\n",p[0].x,p[0].y);
}
else if(n <= 4)
{
Point p0 = Point( (p[0].x+p[1].x)/2 , (p[0].y + p[1].y) /2);
double r = dist(p0,p[0]);
printf("%.12f %.12f %.12f\n",p0.x,p0.y,r);
}
else
{
int N = 1000000;
Point p0;
double r;
random_device rd;
bool f = 0;
while(N--)
{
int a = 0,b = 0,c = 0;
a = ((rd() << 15 | rd()) % n + n) % n;
b = ((rd() << 15 | rd()) % n + n) % n;
c = ((rd() << 15 | rd()) % n + n) % n;
while(b == a ) b = ((rd() << 15 | rd()) % n + n) % n;
while(c == b ||c == a) c = ((rd() << 15 | rd()) % n + n) % n;
p0 = get_circle(p[a],p[b],p[c]);
if(fabs(p0.x) > 1e9 || fabs(p0.y) > 1e9) continue;
r = dist(p0,p[a]);
int cnt = 0;
for(int i = 0;i<n;i++)
{
if(fabs(dist(p[i],p0) - r) < eps)
{
cnt++;
if(cnt >= k)
{
f = 1;
break;
}
}
}
if(f)
{
printf("%.12f %.12f %.12f\n",p0.x,p0.y,r);
break;
}
}
if(!f)printf("%.12f %.12f %.12f\n",p0.x,p0.y,r);
}
}
return 0;
}
/*
1
4
0 1
1 0
-1 0
0 -1
*/