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

原创 2016年05月30日 20:17:32


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);
}

Codeforces Round #209 (Div. 2)-C. Prime Number(set)和D. Pair of Numbers(线段树)

不停的提取公因式。因为牵扯到0,最后取min(ans,sum)。原来很傻的去人工模拟。 #include #include #include #include #include using names...

Codeforces Round #365 (Div. 2) A(暴力) B(数学技巧) C(二分)D(线段树+离散)E(乘除法DP+约数分解+map映射)

传送门:A. Mishka and Game 暴力记录两人赢的次数,最后将次数再比较一次即可 #include using namespace std; int n; int main()...

Codeforces Round #340 (Div. 2) (629A,629B,629C(排列组合,动态规划),629D(线段树))

Far Relative’s Birthday Cake 题目链接: http://www.codeforces.com/problemset/problem/629/A 解题思路: ...

【线段树】 Codeforces Round #223 (Div. 1) C - Sereja and Brackets

离线,按照r递增的顺序将询问排序,然后用线段树做。。 #include #include #include #include #include #include #include #i...

Codeforces Round #200 (Div. 1) D. Water Tree(dfs序+线段树)

题目链接:点击打开链接 思路: dfs序其实是很水的东西。  和树链剖分一样, 都是对树链的hash。 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值。 该题需要...

Codeforces Round #292 (Div. 1) C. Drazil and Park 线段树维护

题意:圆上,询问任意一段弧中,任意两点的距离+两点的权值和的最大值。 先将圆展开,1,2,……n,1,2,……,n,变为段 线段树中,每段记录 1. 当前段最大值, 2. 段中的任意点...

Codeforces Round #225 (Div. 1)C(dfs+线段树)

C. Propagating tree time limit per test 2 seconds memory limit per test 256 megabytes ...
  • cq_phqg
  • cq_phqg
  • 2014年12月13日 00:16
  • 618

Codeforces Round #352 (Div. 2) C D

Codeforces Round #352 (Div. 2) C. Recycling Bottles 题目链接:点这里!!!! 题意: A、B两个人的任务负责把地图上的n个...

codeforces div2 round388 D Voting 线段树

/* 题目描述:有n条(1
  • jijijix
  • jijijix
  • 2017年01月19日 12:50
  • 102

Codeforces Round #197 (Div. 2) D. Xenia and Bit Operations - 线段树

D. Xenia and Bit Operations time limit per test 2 seconds memory limit per test 256 megabytes ...
  • mr_zys
  • mr_zys
  • 2013年08月27日 21:03
  • 1200
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Codeforces Round #352 div1 C D (智商+线段树)
举报原因:
原因补充:

(最多只允许输入30个字)