B
思路
计算几何题。首先确定合法情况下必定只有五个不同的端点,可以用set维护这个特性。在此基础上,找到拥有共同端点的两条线,也就是字母‘A’的腰,求出他们的长度,根据勾股定理确定他们的夹角是否合法。
对于第三条边,假如我们要判断其端点C是否在AB上,可以用AC和BC的斜率是否相等以及纵坐标是否同号(因为要考虑C在AB延长线上的情况)来判断,在此过程中还可以顺便求出短边与长边的长度比,将其塞到一个check函数中方便日后调用。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef long double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void say() {}
void say_() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void say(T _, T2... oth)
{
Out(_);
putchar('\n');
say(oth...);
}
template <typename T, typename... T2>
inline void say_(T _, T2... oth)
{
Out(_);
putchar(' ');
say_(oth...);
}
/*#################################*/
ll cnt;
db eps=0.25;
pii a[10];
set<pii> had;
struct seg
{
ll x1,y1,x2,y2,len;
void print()
{
say_(x1,y1,x2,y2,len);
puts("");
}
}b[5];
ll G_dis(ll x1,ll y1,ll x2,ll y2)
{
return pow(x1-x2,2)+pow(y1-y2,2);
}
pii check(ll x1,ll y1,ll x2,ll y2,ll x3,ll y3)
{
// say_(x1,y1,x2,y2,x3,y3);
// puts("");
pii ret=make_pair(-1,-1);
if(x1==x3 || x2==x3)
{
if(x1==x3 && x2==x3 && db(min(abs(y1-y3),abs(y2-y3)))/db(max(abs(y1-y3),abs(y2-y3)))>=0.25)
ret=make_pair(1,1);
return ret;
}
db k1=db((y1-y3))/db((x1-x3)),k2=db((y2-y3))/db((x2-x3));
// cout<<k1<<"?????"<<k2<<endl;
if(k1!=k2 || (y1-y3)*(y2-y3)>=0)
return ret;
db first=sqrt(min(G_dis(x1,y1,x3,y3),G_dis(x2,y2,x3,y3)));
db second=sqrt(max(G_dis(x1,y1,x3,y3),G_dis(x2,y2,x3,y3)));
// printf("%.0Lf %.0Lf %.4Lf\n",first,second,first/second);
if(first/second<eps)
return ret=make_pair(-1,-1);
else
return ret=make_pair(first,second);
}
void solve()
{
++cnt;
had.clear();
ll p;
rep(i,1,6)
{
read(a[i].first,a[i].second);
if(had.find(a[i])!=had.end())
p=i;
had.insert(a[i]);
}
rep(i,2,6)
{
a[i].first-=a[1].first;
a[i].second-=a[1].second;
}
a[1].first=0;
a[1].second=0;
// rep(i,1,6)
// {
// say_(a[i].first,a[i].second);
// puts("");
// }
// if(cnt==35)
// {
// rep(i,1,6)
// {
// say_(a[i].first,a[i].second);
// puts("");
// }
// }
if(had.size()!=5)
{
puts("NO");
return;
}
ll sum=0;
seg fir,sec,thr;
fir.x1=LLm;
rep(i,1,3)
{
ll tmp=i<<1;
b[i]=seg({a[tmp-1].first,a[tmp-1].second,a[tmp].first,a[tmp].second});
b[i].len=G_dis(b[i].x1,b[i].y1,b[i].x2,b[i].y2);
if(a[tmp]!=a[p] && a[tmp-1]!=a[p])
{
thr=b[i];
}
else
{
if(fir.x1!=LLm)
sec=b[i];
else
fir=b[i];
sum+=b[i].len;
}
}
pii tmpa,tmpb;
if(make_pair(fir.x1,fir.y1)!=a[p])
tmpa=make_pair(fir.x1,fir.y1);
else
tmpa=make_pair(fir.x2,fir.y2);
if(make_pair(sec.x1,sec.y1)!=a[p])
tmpb=make_pair(sec.x1,sec.y1);
else
tmpb=make_pair(sec.x2,sec.y2);
// say_(tmpa.first,tmpa.second,tmpb.first,tmpb.second);
// puts("");
// say(sum);
// say(G_dis(23902806,17823588,0,0)+G_dis(23902806,17823588,-82089,59655591));
// say(G_dis(tmpa.first,tmpa.second,tmpb.first,tmpb.second));
if(sum<G_dis(tmpa.first,tmpa.second,tmpb.first,tmpb.second))
{
puts("NO");
return;
}
// say(sum);
// fir.print();
// sec.print();
// thr.print();
// puts("::::::");
// pii cur=check(fir.x1,fir.y1,fir.x2,fir.y2,thr.x1,thr.y1);
// cout<<cur.first<<" [][][][][][]"<<cur.second<<endl;
if(check(fir.x1,fir.y1,fir.x2,fir.y2,thr.x1,thr.y1).first==-1)
{
if(check(fir.x1,fir.y1,fir.x2,fir.y2,thr.x2,thr.y2).first==-1)
{
puts("NO");
return;
}
if(check(sec.x1,sec.y1,sec.x2,sec.y2,thr.x1,thr.y1).first==-1)
{
// cout<<"???????"<<endl;
puts("NO");
return;
}
puts("YES");
return;
}
// cout<<"::::::::::::"<<endl;
// cur=check(sec.x1,sec.y1,sec.x2,sec.y2,thr.x1,thr.y1);
// cout<<cur.first<<">>> "<<cur.second<<endl;
// puts("::::::::::::::::::");
if(check(sec.x1,sec.y1,sec.x2,sec.y2,thr.x2,thr.y2).first==-1)
{
puts("NO");
return;
}
puts("YES");
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
C
思路
dp题。在某个元素大小下降的位置,对于较小的元素,必然是将其变成左边的元素或者右边的元素。因此最终的序列中的元素必然在原序列中出现过。
设原序列排序后的得到的序列为,并设为当前个元素单调不下降,且时需要的最少步数。由前面的结论可以知道,或,因此。采用滚动数组优化可以压缩至一维空间。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void say() {}
void say_() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void say(T _, T2... oth)
{
Out(_);
putchar('\n');
say(oth...);
}
template <typename T, typename... T2>
inline void say_(T _, T2... oth)
{
Out(_);
putchar(' ');
say_(oth...);
}
/*#################################*/
const ll N=5005;
ll n;
ll a[N],b[N],f[N];
int main()
{
read(n);
rep(i,1,n)
{
read(a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
rep(i,1,n)
{
rep(j,1,n)
{
f[j]+=abs(a[i]-b[j]);
if(j>1)
f[j]=min(f[j-1],f[j]);
}
}
say(f[n]);
}
E
思路
暴力跳过去必然超时,因此要分块,一块一块地跳。
预处理出从第个点跳到其所在块结尾所需的步数以及其到达结尾时所处的位置,每次更新第个点时,后面点的信息必然不会受影响,因此只更新左边的同块的点,复杂度为。询问时,直接一步跳到块中的最后一个点,再跳一步到下一个块,重复上述过程直到跳出界,复杂度也为。因此总复杂度为。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef int ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void say() {}
void say_() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void say(T _, T2... oth)
{
Out(_);
putchar('\n');
say(oth...);
}
template <typename T, typename... T2>
inline void say_(T _, T2... oth)
{
Out(_);
putchar(' ');
say_(oth...);
}
/*#################################*/
const ll N=1E5+10;
ll n,m,unit;
ll a[N],lst[N],cnt[N],block[N];
void print()
{
rep(i,1,n)
say_(lst[i]);
puts("");
rep(i,1,n)
say_(cnt[i]);
puts("");
}
void update(ll x,ll val)
{
a[x]=val;
for(int i=x;block[i]==block[x];--i)
{
ll nxt=i+a[i];
if(block[i]!=block[nxt])
{
cnt[i]=0;
lst[i]=i;
continue;
}
cnt[i]=cnt[nxt]+1;
lst[i]=lst[nxt];
}
}
void query(ll x)
{
ll cur=x,tot=1;
while(cur<=n)
{
tot+=cnt[cur];
cur=lst[cur];
if(cur+a[cur]<=n)
{
cur+=a[cur];
++tot;
}
else
break;
}
printf("%d %d\n",cur,tot);
}
int main()
{
read(n,m);
unit=ceil(sqrt(n));
rep(i,1,n)
block[i]=(i-1)/unit+1;
rep(i,1,n)
read(a[i]);
for(int i=n;i>=1;--i)
{
ll nxt=i+a[i];
if(block[i]!=block[nxt])
{
lst[i]=i;
continue;
}
cnt[i]=cnt[nxt]+1;
lst[i]=lst[nxt];
}
ll ty,x,y;
// print();
while(m--)
{
read(ty);
if(ty==0)
{
read(x,y);
update(x,y);
}
else
{
read(x);
query(x);
}
}
// print();
}