T1~T4 都是比较简单的水题了(实现和想的过程都挺简单的)
T7是树状数组
T5平衡树打了 F H Q FHQ FHQ但因为区间加出锅考后A了
T6T9貌似都是数学结论题
T8图论题
T10 w d f wdf wdf???
做题&改题概况:
T1,T3,T4 考场秒切
接着T7在 z y c zyc zyc大佬的指导下想出
之后一直肛T5,敲了无旋Treap,但因为不会区间加饮恨
最后比较颓,T2 w y c wyc wyc大佬讲清题意后切掉
考后秒改T5
T8第二周完成
T6,T9数论题
T6类欧几里得
T9积性函数前缀和
T10 S O S D p SOSDp SOSDp问题完全不会
题解们:T1~T5+T7,如下
T8
T6,T9,T10
描述:
设 f i f_i fi表示每个数的最小质因子,求其前缀和
n ≤ 3 × 1 0 7 n\leq3\times 10^7 n≤3×107
题解:
这不是线性筛的 v a l val val数组嘛。。。。
时间复杂度: O ( n ) O(n) O(n)
代码:
#include
using namespace std;
const int N=4e7;
int n,v[N+1],prime[N+1],m;
long long ans;
signed main()
{
scanf("%d",&n);
for(register int i=2;i<=n;i++)
{
if(!v[i])
{
v[i]=i;prime[++m]=i;
}
for(register int j=1;j<=m;j++)
{
if(prime[j]>v[i]||prime[j]*i>n) break;
v[i*prime[j]]=prime[j];
}
ans+=v[i];
}
printf("%lld\n",ans);
}
描述:
n ≤ 5 × 1 0 4 , k ≤ 5 , q ≤ 1 0 4 , 1 ≤ x ≤ n , 1 ≤ l e n ≤ n n\leq 5\times 10^4,k\leq 5,q\leq 10^4,1\leq x\leq n,1\leq len\leq n n≤5×104,k≤5,q≤104,1≤x≤n,1≤len≤n
题解:
k k k这么小。。。
暴力瞎搞就行了啊,用map维护
时间复杂度: O ( ( n + q ) k 3 l o g k ) O((n+q)k^3logk) O((n+q)k3logk)
#include
#include
#include
using namespace std;int n,k,q,x,len,ans;
map<string,int>m,m2;
string s[50001],ls;
signed main()
{
cin>>n>>k;
for(register int i=1;i<=n;i++)
{
cin>>s[i];
for(register int j=0;j<k;j++)
for(register int l=1;j+l-1<k;l++)
m[s[i].substr(j,l)]++;
}
cin>>q;
while(q--)
{
cin>>x>>len;ans=0;m2.clear();
for(register int i=0;i<k;i++)
for(register int j=1;i+j-1<k;j++)
m2[s[x].substr(i,j)]++;
for(register int i=0;i+len-1<k;i++) ans+=len*(m[s[x].substr(i,len)]-m2[s[x].substr(i,len)]);
cout<<ans<<endl;
}
}
描述:
给定 n n n个数,要把他们分成 k k k个非空的组,使得每组的极差和最大
k ≤ n ≤ 1 0 5 k\leq n\leq 10^5 k≤n≤105
题解:
显然贪心嘛,每组必然是最大的最小的,然后第二大的第二小的以此类推
注意特判不够分组的情况
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
代码:
#include
#include
using namespace std;
const int N=1e6;
int a[N],n,k,l,r;
long long ans;
signed main()
{
scanf("%d%d",&n,&k);
if(n==k) return putchar(48)&0;
for(register int i=1;i<=n;i++) scanf("%d",a+i);
sort(a+1,a+1+n);l=1;r=n;
while(k&&l<=r&&(r-l+1)>k)
{
ans+=a[r]-a[l];
r--;l++;k--;
}
printf("%lld",ans);
}
题解:
判断四边相等就知道是否是菱形了,由于数据水,这样我就过了。。。
时间复杂度: O ( 4 2 × 4 ! ) = O ( 1 ) O(4^2\times 4!)=O(1) O(42×4!)=O(1)
至于垂直随便判断一下就行了
代码:
#include
#include
#include
#define pd if(check()) return puts("hai xing")&0
using namespace std;
double x[5],y[5];
double dist(int i,int j){return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}
bool xs(int a,int b,int c,int d)
{
return dist(a,b)==dist(a,c)&&dist(a,b)==dist(c,d)&&dist(a,b)==dist(b,d);
}
bool check()
{
int qpl[4]={1,2,3,4};
do
{
if(xs(qpl[0],qpl[1],qpl[2],qpl[3])) return true;
}while(next_permutation(qpl+1,qpl+5));
return false;
}
signed main()
{
for(register int i=1;i<=4;i++) scanf("%lf%lf",x+i,y+i);
if(check()) return puts("wen")&0;
for(register int i=1;i<=4;i++)
{
x[i]++;pd;x[i]--;
x[i]--;pd;x[i]++;
y[i]++;pd;y[i]--;
y[i]--;pd;y[i]++;
}
puts("wo jue de bu xing");
}
数据范围: n ≤ 1 0 5 n\leq 10^5 n≤105
题解:
没有第一条就是一道sb线段树题
加上了就是一道sb平衡树题
这里的平衡树是指可以维护序列的平衡树,可以用 S p l a y Splay Splay或无旋 T r e a p Treap Treap解决
时间复杂度: O ( ( n + q ) l o g n ) O((n+q)logn) O((n+q)logn)
代码:
#include
#include
#include
#include
#include
#define ll long long
#define INF 0x3f3f3f3f
#define ls(p) tree[p].lson
#define rs(p) tree[p].rson
#define tls(p) tree[ls(p)]
#define trs(p) tree[rs(p)]
#define t(p) tree[p]
#define tpi t(++tot)
#define tp t(tot)
#define N 200001
using namespace std;int n,opt,a,b,x,rt,p,m,y,z,v;
typedef long long LL;
struct node{int lson,rson,tag,size,rand;LL sum,val;}tree[(N<<7)+10];
inline LL read()
{
char c;int d=1;LL f=0;
while(c=getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register LL x)
{
if(x<0)putchar(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
inline void change(int x,int v){t(x).val+=v;t(x).tag+=v;t(x).sum+=1ll*t(x).size*v;return;}
inline int new_node(long long v=0)//新建节点
{
static int tot(0);
tpi.val=v;tp.sum=v;tp.rand=rand();tp.size=1;
return tot;
}
inline int copy_node(int p)//复制节点
{
int ret=new_node();
t(ret)=t(p);
return ret;
}
inline void push_up(int p)//上传
{
t(p).size=tls(p).size+trs(p).size+1;
t(p).sum=tls(p).sum+trs(p).sum+t(p).val;
return;
}
inline void push_down(int p)//下传
{
if(!t(p).tag||!p) return;
LL dif=t(p).tag;
if(ls(p)) change(ls(p),dif);
if(rs(p)) change(rs(p),dif);
tree[p].tag=0;
return;
}
inline void split(int p,int k,int &x,int &y)//分裂
{
if(!p) {x=y=0;return;}
push_down(p);
if(tls(p).size<k) {x=copy_node(p);split(rs(x),k-tls(p).size-1,rs(x),y);push_up(x);}
else {y=copy_node(p);split(ls(y),k,x,ls(y));push_up(y);}
return;
}
inline int merge(int x,int y)//合并
{
if(!x||!y) return x|y;
push_down(x);push_down(y);
if(t(x).rand<t(y).rand){rs(x)=merge(rs(x),y);push_up(x);return x;}
else {ls(y)=merge(x,ls(y));push_up(y);return y;}
}
inline void add(int l,int r,int v)
{
split(rt,b,x,z);split(x,a-1,x,y);
change(y,v);
rt=merge(merge(x,y),z);
return;
}
signed main()
{
srand(time(0));
n=read();
for(register int i=1;i<=n;i++) x=read(),rt=merge(rt,new_node(x));
m=read();
while(m--)
{
opt=read();
if(opt==1)
{
a=read()-1;
split(rt,a,x,y);
rt=merge(merge(x,new_node(0)),y);
continue;
}
if(opt==2)
{
a=read();b=read();v=read();
add(a,b,v);
}
if(opt==3)
{
a=read();b=read();
split(rt,b,x,z);split(x,a-1,x,y);
write(t(y).sum);putchar(10);
rt=merge(merge(x,y),z);
continue;
}
}
}
描述:
数据范围:
n , k ≤ 2 × 1 0 5 n,k\leq 2\times 10^5 n,k≤2×105
题解:
显然二分,用树状数组维护可以带走多少点,由于二分的只能是整数,所以所有的距离向上取整即可
时间复杂度: O ( n l o g k ) O(nlogk) O(nlogk)
代码:
#include
#include
#include
#define lb(x) x&-x
using namespace std;int n,op;
long long x,y,z,a[200010],l,r,maxn,mid,ans,c[300010];
inline void add(int x){for(;x<=300000;x+=lb(x)) c[x]++;return;}
inline int get(int x){int s=0;for(;x;x-=lb(x)) s+=c[x];return s;}
signed main()
{
scanf("%d",&n);
while(n--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%lld%lld%lld",&x,&y,&z);
add((int)(sqrt(x*x+y*y+z*z)+0.999999999));
}
if(op==2)
{
scanf("%lld",&x);
l=0;r=300000;ans=-1;
while(l<=r)
{
mid=l+r>>1;
if(get(mid)>=x) r=(ans=mid)-1;
else l=mid+1;
}
printf("%lld\n",ans);
}
}
}
我好菜啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊