Comet OJ - 模拟赛 #2 Day2

正题

      今天不会做的题是第一题

      T1

      开场想到T1不会那么难,就直接暴力枚举x的因子,时间复杂度O(n\sqrt x \log_2n),结果拿到了70分的好成绩。

      考虑到x的因子并没有那么多,根本不需要根号去枚举,而是质因数分解之后,暴力dfs枚举因子。

      首先50000以内的质数只有大概3000个左右(并没有那么多,用黎曼猜想估算),其次分解是log的,所以就是O(3000+\log_2 x),题解写的是O(\frac{\sqrt x}{\log x}),我也不知道为什么。然后dfs找因子的复杂度就是O(\sigma_0(x)),这个没有疑问。

      接着暴力用树状数组维护就可以通过。

      但是发现有大约O(n*1536)次修改和O(q)次查询,所以我们只需要一个O(1),O(\sqrt n)的分块维护就可以了。

      T2

      一血好评

      把同一种颜色的坐标提出来,然后考虑一个左边的区间能和那些右边的区间乘起来贡献到答案里面。

      显然要么端点重合,要么隔一个点,要么隔三个点...所以直接分奇偶记录就可以了。

      复杂度O(n+m)

#include<bits/stdc++.h>
using namespace std;

const int N=1000010;
vector<int> F[N];
int n,m;
int t[2],op;
long long ans=0;

int main(){
	scanf("%d %d",&n,&m);
	int x;
	for(int i=1;i<=n;i++) scanf("%d",&x),F[x].push_back(i);
	for(int i=1;i<=m;i++) if(F[i].size()){
		t[0]=t[1]=0;op=0;
		t[op]=F[i][0];F[i].push_back(n+1);
		for(int j=0;j+1<F[i].size();j++){
			ans+=1ll*t[op]*(F[i][j+1]-F[i][j]);
			op^=1;t[op]+=F[i][j+1]-F[i][j];
		}
	}
	printf("%lld\n",ans);
}

      T3

      难得两重lazy写对了,结果被丧心病狂的出题人卡掉了一个点????

扫描二维码关注公众号,回复: 11613498 查看本文章

      首先考虑序列上的情况,树上的情况可以花费log的时间转成序列。

      发现要做的有两种事情,给区间内奇数/偶数加w,区间奇数/偶数求和。

      直接维护发现找不到奇数偶数的关系,我是先发现w为奇数的时候,修改后,要么区间内全同奇,要么区间内全同偶,否则奇偶不变,所以我们先给区间内对应的数加上w,不考虑奇偶变化的情况,再统一修改奇偶情况。

       发现现在到区间上面有两种操作:区间给黑/白点加上w,区间染黑/白。

       发现染黑或者染白后区间就在一起了,所以我们只需要记录四个lazy,区间不在一起之前,给黑/白点加了多少,区间在一起变成什么颜色(不在一起为-1),在一起之后整个区间一共加了多少。

       当然一些基本的区间奇偶和,奇偶数个数分别有多少个还是要记录的,具体可以参照代码,比较好懂。

       开了Ofast才能通过。请教群内的大佬后,这个维护是O(1)下传lazy的,所以可以用LCT做到大常数的一个log。

#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define ls now<<1
#define rs now<<1|1
using namespace std;

const int N=160010;
struct edge{
	int y,next;
}s[N<<1];
int first[N],len=0,n,m,num;
int son[N],tot[N],top[N],fa[N],ima[N],dep[N];
long long t[N<<2][2],sum[N<<2][2],a_lazy[N<<2][2],C[N<<2],A[N<<2];

inline char nc(){
    static char buf[5000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,5000000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int&sum){
    char ch=nc();sum=0;
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return ;
}

void ins(int x,int y){
	s[++len]=(edge){y,first[x]};first[x]=len;
}

void dfs(int x){
	tot[x]=1;
	for(int i=first[x];i!=0;i=s[i].next) if(s[i].y!=fa[x]){
		fa[s[i].y]=x;dep[s[i].y]=dep[x]+1;
		dfs(s[i].y);
		tot[x]+=tot[s[i].y];
		if(tot[s[i].y]>tot[son[x]]) son[x]=s[i].y;
	}
}

void dfs_2(int x,int tp){
	top[x]=tp;ima[x]=++num;
	if(son[x]) dfs_2(son[x],tp);
	for(int i=first[x];i!=0;i=s[i].next) if(s[i].y!=fa[x] && s[i].y!=son[x]) dfs_2(s[i].y,s[i].y);
}

void Add(int now,int op,int c,int l,int r){
	if(C[now]==-1){
		a_lazy[now][op]+=c;
		sum[now][op]+=1ll*t[now][op]*c;
	}
	else if(op==C[now]) A[now]+=c,sum[now][op]+=1ll*(r-l+1)*c;
}

void C_type(int now,int op,int l,int r){
	if(C[now]==-1) A[now]=0;
	sum[now][op]+=sum[now][op^1];sum[now][op^1]=0;
	t[now][op]=r-l+1;t[now][op^1]=0;C[now]=op;
}

void push_down(int now,int l,int r){
	int mid=(l+r)/2;
	if(a_lazy[now][0]) Add(ls,0,a_lazy[now][0],l,mid),Add(rs,0,a_lazy[now][0],mid+1,r);
	if(a_lazy[now][1]) Add(ls,1,a_lazy[now][1],l,mid),Add(rs,1,a_lazy[now][1],mid+1,r);
	if(C[now]!=-1){
		C_type(ls,C[now],l,mid);C_type(rs,C[now],mid+1,r);
		Add(ls,C[now],A[now],l,mid);Add(rs,C[now],A[now],mid+1,r);
	}
	a_lazy[now][0]=a_lazy[now][1]=A[now]=0;
	C[now]=-1;
}

void add(int now,int x,int y,int op,int c,int l=1,int r=n){
	if(x==l && y==r){Add(now,op,c,l,r);return ;}
	push_down(now,l,r);
	int mid=(l+r)/2;
	if(y<=mid) add(ls,x,y,op,c,l,mid);
	else if(mid<x) add(rs,x,y,op,c,mid+1,r); 
	else add(ls,x,mid,op,c,l,mid),add(rs,mid+1,y,op,c,mid+1,r);
	sum[now][op]=sum[ls][op]+sum[rs][op];
}

long long get_sum(int now,int x,int y,int op,int l=1,int r=n){
	if(x==l && y==r) return sum[now][op];
	push_down(now,l,r);
	int mid=(l+r)/2;
	if(y<=mid) return get_sum(ls,x,y,op,l,mid);
	else if(mid<x) return get_sum(rs,x,y,op,mid+1,r);
	else return get_sum(ls,x,mid,op,l,mid)+get_sum(rs,mid+1,y,op,mid+1,r);
}

void c_type(int now,int x,int y,int op,int l=1,int r=n){
	if(x==l && y==r){C_type(now,op,l,r);return ;}
	push_down(now,l,r);
	int mid=(l+r)/2;
	if(y<=mid) c_type(ls,x,y,op,l,mid);
	else if(mid<x) c_type(rs,x,y,op,mid+1,r);
	else c_type(ls,x,mid,op,l,mid),c_type(rs,mid+1,y,op,mid+1,r);
	sum[now][0]=sum[ls][0]+sum[rs][0];
	t[now][0]=t[ls][0]+t[rs][0];
	sum[now][1]=sum[ls][1]+sum[rs][1];
	t[now][1]=t[ls][1]+t[rs][1];
}

long long solve(int type,int x,int y,int c){
	long long ans=get_sum(1,x,y,type);
	if(type==0){
		add(1,x,y,1,c);
		if(c&1) c_type(1,x,y,0);
	}
	if(type==1){
		add(1,x,y,0,c);
		if(c&1) c_type(1,x,y,1);
	}
	return ans;
}

void build(int now,int l,int r){
	t[now][0]=r-l+1;C[now]=-1;
	if(l==r) return ;
	int mid=(l+r)/2;
	build(ls,l,mid);
	build(rs,mid+1,r);
}

int main(){
	read(n);read(m);
	int type,x,y,c,tx,ty;
	long long ans=0;
	for(int i=1;i<n;i++) read(x),read(y),ins(x,y),ins(y,x);
	dep[1]=1;dfs(1);dfs_2(1,1);
	build(1,1,n);
	while(m--){
		read(type),read(x),read(y),read(c);type--;
		ans=0;tx=top[x];ty=top[y];
		while(tx!=ty){
			if(dep[tx]>dep[ty]) swap(x,y),swap(tx,ty);
			ans+=solve(type,ima[ty],ima[y],c);
			y=fa[ty];ty=top[y];
		}
		if(dep[x]>dep[y]) swap(x,y);
		ans+=solve(type,ima[x],ima[y],c);
		printf("%lld\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/103332618
今日推荐