9.3
作者:互联网
ABC139F
题意:
给定\(n\)个向量,从中任意选择,最后组合起来的向量长度最长。
\(n\leq 100\)
题解:
神仙题。
肯定不会选两个方向差太多的向量。
所以把所有向量极角排序后,选择的向量是连续的一段。
注意要把排序后的向量数组延长一倍形成环。
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
const int N=1e6+10,mod=998244353,inf=2e15;
void __init(int n=2000) {}
inline void main()
{
int n;
cin>>n;
typedef array<double,2> pr;
vector<pr> a(2*n);
for(int i=0;i<n;++i)
{
cin>>a[i][0]>>a[i][1];
}
sort(a.begin(),a.begin()+n,[&](pr x,pr y){return atan2(x[1],x[0])<atan2(y[1],y[0]);});
for(int i=n;i<2*n;++i) a[i]=a[i-n];
double ans=0;
for(int i=0;i<n;++i)
{
double sumx=0,sumy=0;
for(int j=i;j<i+n;++j)
{
sumx+=a[j][0],sumy+=a[j][1];
ans=max(ans,sqrt(sumx*sumx+sumy*sumy));
}
}
cout<<fixed<<setprecision(12)<<ans<<'\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
red::__init();
int qwq=1; //cin>>qwq;
while(qwq--) red::main();
return 0;
}
/*
1 7 5 6 8 2 6 5
0 8 5 6 8 0 8 5
3
5 6 5
3 8 5
2
3
8
*/
ABC140E
题意:
给定一个排列,求\(\sum_{l=1}^n\sum_{r=l+1}^nX_{l,r}\)
其中\(X_{l,r}\)是\(p[l]\sim p[r]\)中第二大的数字。
\(n\leq 10^5\)
题解:
考虑每个数字的贡献,它作为那些段的第二大数字。
设一个数字\(x\),位置在\(p\),左边第一个大于它的数字位置是\(l\),第二个是\(ll\),右边同理\(r,rr\)
那么它作为第二大,很明显左边或者右边只能有一个比自己大。
所以可行的范围,左端点取值在\((ll,l]\),右端点取值在\([p,r)\)
或者左端点在\((l,p]\),右端点在\([r,rr)\)
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
const int N=1e6+10,mod=998244353,inf=2e15;
void __init(int n=2000) {}
inline void main()
{
int n;
cin>>n;
typedef array<int,2> pr;
vector<pr> a(n+1);
for(int i=1;i<=n;++i)
{
int x;cin>>x;
a[i]=pr{x,i};
}
sort(a.begin()+1,a.end());
reverse(a.begin()+1,a.end());
multiset<int> q;
q.insert(0),q.insert(0);
q.insert(n+1),q.insert(n+1);
int ans=0;
for(int i=1;i<=n;++i)
{
int x=a[i][0],p=a[i][1];
auto it=q.lower_bound(a[i][1]);
int ll=0,l=0,r=n+1,rr=n+1;
if(it!=q.end())
{
r=*it;
++it;
if(it!=q.end()) rr=*it;
--it;
}
if(it!=q.begin())
{
--it;
l=*it;
if(it!=q.begin())
{
--it;
ll=*it;
}
}
if(l>=1) ans+=max(0ll,(r-a[i][1])*(l-ll)*x);
if(r<=n) ans+=max(0ll,(a[i][1]-l)*(rr-r)*x);
q.insert(a[i][1]);
}
cout<<ans<<'\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
red::__init();
int qwq=1; //cin>>qwq;
while(qwq--) red::main();
return 0;
}
/*
1 7 5 6 8 2 6 5
0 8 5 6 8 0 8 5
3
5 6 5
3 8 5
2
3
8
*/
ABC141F
题意:
给\(n\)个数,把他们分成两组,两组各自异或起来,再把两组的异或和加起来,求最大值
\(n\leq 10^5,0\leq a_i<2^{60}\)
题解:
很神。
这种题按位考虑
如果这一位有奇数个\(1\),不管怎么分,这一位的贡献都是\(1\),不用考虑这些位
如果有偶数个\(1\),不管怎么分,这一位的异或和都是\(0\)。
也就是说第一组的异或和一定等于第二组的异或和。
所以就是用线性基求个最大值就行了。
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
const int N=1e6+10,mod=998244353,inf=2e15;
void __init(int n=2000) {}
inline void main()
{
int n;
cin>>n;
vector<int> a(n);
vector<int> s(60);
for(int i=0;i<n;++i)
{
cin>>a[i];
for(int k=0;k<60;++k) s[k]+=(a[i]>>k)&1;
}
vector<int> p(60);
auto insert=[&](int x) -> void
{
for(int k=59;~k;--k) if((x>>k)&1)
{
if(!p[k]) {p[k]=x;return;}
x^=p[k];
}
};
auto query=[&]() -> int
{
int x=0;
for(int k=59;~k;--k)
{
x=max(x,x^p[k]);
}
return x;
};
int ans=0;
for(int k=0;k<60;++k)
{
if(s[k]&1) ans|=(1ll<<k);
}
for(int i=0;i<n;++i)
{
int x=a[i];
for(int k=0;k<60;++k) if(s[k]&1)
{
x&=(-1)^(1ll<<k);
}
insert(x);
}
cout<<ans+2*query()<<'\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
red::__init();
int qwq=1; //cin>>qwq;
while(qwq--) red::main();
return 0;
}
/*
1 7 5 6 8 2 6 5
0 8 5 6 8 0 8 5
3
5 6 5
3 8 5
2
3
8
*/
标签:9.3,return,int,void,long,main,define 来源: https://www.cnblogs.com/knife-rose/p/16654091.html