Codeforces Round #352 div1 C D (智商+线段树)


Ultimate Weirdness of an Array

题意:给一个数列ai, f(i,j) 定义为除去i到j之间的数后最大gcd(ai, aj)的值, 求所有f(i,j)之和



#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <bitset>
#include <queue>
#include <set>	
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;

#define LL long long
#define ULL unsigned long long
#define eps 1e-9
#define N (200000+ 10)
#define M (10000000 + 10)
#define pii pair<int,int>
#define MP make_pair
#define inf 0x3f3f3f3f
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define ls (i<<1)
#define rs (i<<1|1)
#define mod 9973


int a[N];
int l1[N], l2[N], r1[N], r2[N];

void mark(int j, int i) {
	if(!l1[j]) l1[j] = i;
	else if(!l2[j]) l2[j] = i;
	r2[j] = r1[j];
	r1[j] = i;
}

int mx[N<<2], mi[N<<2];
LL b[N],s[N<<2];
int c[N<<2];
void update(int l, int r, int v, int ll, int rr, int i) {
	if(l > r) return ;
	if(mi[i] >= v) return ;
	if(ll == rr) {
		mx[i] = max(mx[i], v);
		mi[i] = mx[i];
		s[i] = mx[i];
		return ;
	}
	if(ll == l && r ==  rr && mx[i] <= v) {
		mx[i] = mi[i] = v;
		s[i] = (LL)v * (rr-ll+1);
		c[i] = v;
		return ;
	}
	if(c[i]) {
		int len = rr-ll+1;
		c[ls] = c[i], c[rs] = c[i];
		mi[ls] = mx[ls] = c[i], mi[rs] = mx[rs] =c[i];
		s[ls] = (LL)(len-len/2) * c[i], s[rs] = (LL)len/2 * c[i];
		c[i] = 0;
	}
	int md = ll+rr>> 1;
	if(r <= md) update(l, r, v, lson);
	else if(l > md) update(l, r, v, rson);
	else update(l, md, v, lson), update(md+1, r, v, rson);
	mx[i] = max(mx[ls], mx[rs]);
	mi[i] = min(mi[ls], mi[rs]);
	s[i] = s[ls] + s[rs];
}


int main() {
	//freopen("in.txt", "r", stdin);
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for(int i = 1; i <= n; ++i) {
		int y = (int)sqrt(a[i] *1.0);
		for(int j = 1; j <= y; ++j) {
			if(a[i] % j == 0) {
				mark(j, i);
				if(j * j != a[i]) 
					mark(a[i]/j, i);
			}
		}
	}
	for(int i = 1; i <= n; ++i) update(i, i, i, 1, n, 1);
	int Max = 200005;
	for(int i = Max; i >= 1; --i) {
		if(l1[i] != r1[i]) {
			update(1, l1[i], r2[i], 1, n, 1);
			update(l1[i]+1, l2[i], r1[i], 1, n, 1);
			update(l2[i]+1, n, n+1, 1, n, 1);
		}
		b[i] = (LL)n*(n+1) - s[1];

		
	}	
	LL ans = 0;
	for(int i = 1; i < Max; ++i)
		ans += (b[i+1]-b[i]) * i;
	printf("%I64d\n", ans);
}

Roads in Yusland


题意:给一个有根树,m条路径u,v,费用为ci,v是u的祖先,选取一些路径覆盖树上所有边


#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <bitset>
#include <queue>
#include <set>	
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;

#define LL long long
#define ULL unsigned long long
#define eps 1e-9
#define N (300000+ 10)
#define M (1000000 + 10)
#define pii pair<int,int>
#define MP make_pair
#define md (ll+rr>>1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define ls (i<<1)
#define rs (i<<1|1)
#define mod 9973

const LL inf = (LL) 1e15;
int fst[N], vv[M], nxt[M], e;

void init() {
	memset(fst, -1, sizeof fst);
	e = 0;
}

void add(int u, int v) {
	vv[e] =v, nxt[e] = fst[u], fst[u] = e++;
}

vector<int> st[N], ed[N];
int sid[N], tid[N], id[N], dc;

void dfs(int u, int p) {
	sid[u] = dc+1;
	for(int i = 0; i < st[u].size(); ++i) id[st[u][i]] = ++dc;
	for(int i = fst[u]; ~i; i = nxt[i] ){
		int v = vv[i];
		if(v == p) continue;
		dfs(v, u);
	}
	tid[u] = dc;
}

struct node {
	int u, v, c;
	node() {}
	node(int u, int v, int c) : u(u), v(v), c(c) {};
}que[N];


int n, m;
LL mi[N<<2], lazy[N<<2];
LL dp[N];

void build(int ll, int rr, int i) {
	if(ll > rr) return ;
	mi[i] = inf;
	if(ll == rr) return ;
	build(lson);
	build(rson);
}

void up(int i) {
	mi[i] = min(mi[ls], mi[rs]);
	mi[i] = min(mi[i], inf);
}

void down(int i) {
	if(lazy[i]) {
		mi[ls] = min(inf, mi[ls] + lazy[i]);
		mi[rs] = min(inf, mi[rs] + lazy[i]);
		lazy[ls] += lazy[i]; lazy[ls] = min(inf, lazy[ls]);
		lazy[rs] += lazy[i]; lazy[rs] = min(inf, lazy[rs]);
		lazy[i] = 0;
	}
}
LL query(int l, int r, int ll, int rr, int i) {
	if(l > r) return inf;
	if(l == ll && r == rr) {
		return mi[i];
	}
	down(i);
	if(r <= md) return query(l, r, lson);
	else if(l > md) return query(l,r, rson);
	else return  min(query(l, md, lson), query(md+1, r, rson));
}


void update(int x, LL v, int ll, int rr, int i) {
	if(ll == rr) {
		mi[i] = v;
		return ;
	}
	down(i);
	if(x <= md) update(x, v, lson);
	else update(x, v, rson);
	up(i);
}

void update(int l, int r, LL v, int ll, int rr, int i) {
	if(l > r) return ;
	if(l == ll && r == rr) {
		mi[i] = min(inf, mi[i] + v);
		lazy[i] += v;
		lazy[i] = min(inf, lazy[i]);
		return ;
	}
	down(i);
	if(r <= md) update(l, r, v, lson);
	else if(l > md) update(l, r, v, rson);
	else update(l, md, v, lson), update(md+1, r, v, rson);
	up(i);
}
void f(int u, int p) {
	LL tot = 0;
	for(int i = fst[u]; ~i; i = nxt[i]) {
		int v = vv[i];
		if(v == p) continue;
		f(v, u);
		tot += dp[v];
	}
	if(u == 1) {
		dp[u] = tot;
		return ;
	}
	for(int i = 0; i < st[u].size(); ++i) 
		update(id[st[u][i]],tot+ que[st[u][i]].c , 1, m, 1);
	for(int i = 0; i < ed[u].size(); ++i)
		update(id[ed[u][i]], inf, 1, m, 1);
	for(int i = fst[u]; ~i; i = nxt[i]) {
		int v = vv[i];
		if(v == p) continue;
		update(sid[v], tid[v], tot-dp[v], 1, m, 1);
	}
	dp[u] = query(sid[u], tid[u], 1, m, 1);
}

int main() {
	//freopen("in.txt", "r", stdin);
	
	scanf("%d%d", &n, &m);
	int u, v;
	init();
	for(int i = 1; i < n; ++i)
	{
		scanf("%d%d", &u, &v);
		add(u, v), add(v, u);
	}
	for(int i = 1; i <= m; ++i) {
		int w;
		scanf("%d%d%d",&u, &v, &w);
		que[i] = node(u, v, w);
		st[u].push_back(i);
		ed[v].push_back(i);
	}
	dfs(1, 0);
	//build(1, m, 1);
	f(1, 0);
	LL ans = dp[1];
	if(ans >= inf || ans < 0) ans = -1;
	printf("%I64d\n", ans);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值