BestCoder Round #45
2015-06-21 05:09
369 查看
继续宣传:
新博客:http://shijieyywd.com/?p=120
呃。。虽然发挥不咋样但是状态似乎回转了一点。。1001.Dylans loves numbers
问一个整数n的二进制中有多少组1。如果两个1之间有若干个(至少一个)0挡住,他们就不是一组的,否则他们就是一组的。
嗯。。直接模拟吧。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; int T; long long n; int solve() { int cnt = 0; bool flag = false; while (n) { if (n & 1) { if (!flag) cnt++; flag = 1; } else flag = 0; n >>= 1; } return cnt; } int main() { scanf("%d", &T); while (T--) { cin >> n; printf("%d\n", solve()); } return 0; }
1002.Dylans loves sequence
给你n个数,q个询问,每个询问要求输出[l, r]这些数中逆序对的个数。因为n<=1000所以直接n2n^2枚举i,j求出[i, j]的逆序对个数就可以啦。
逆序对用树状数组维护,这里不再赘述。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #define MAXN 1005 using namespace std; struct Node { int val; int pos; bool operator < (const Node &n) const { return val < n.val; } }; int n, q; int arr[MAXN]; Node temp[MAXN]; int c[MAXN]; int reflect[MAXN]; int lowBit(int i) { return i & (-i); } void update(int x, int d) { while (x <= n) { c[x] += d; x += lowBit(x); } } int getSum(int x) { int ans = 0; while (x > 0) { ans += c[x]; x -= lowBit(x); } return ans; } int ans[1005][1005]; int main() { scanf("%d %d", &n, &q); for (int i = 1; i <= n; i++) scanf("%d", &arr[i]); for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { temp[j - i + 1].val = arr[j]; temp[j - i + 1].pos = j - i + 1; } stable_sort(temp + 1, temp + n - i + 2); for (int j = 1; j <= n - i + 1; j++) { reflect[temp[j].pos] = j; } memset(c, 0, sizeof(c)); for (int j = 1; j <= n - i + 1; j++) { update(reflect[j], 1); ans[i][j + i - 1] = ans[i][j + i - 2] + j - getSum(reflect[j]); } } int a, b; for (int i = 0; i < q; i++) { scanf("%d %d", &a, &b); printf("%d\n", ans[a]); } return 0; }
[b]1003.Dylans loves tree
一棵n个点的树,每个点有点权,树上节点标号1~n。有q个询问,形式如下:
0 x y:把第x个点的权值修改为y。
1 x y:对于x~y路径上的每一种点权,是否都出现奇数次?保证每次询问的路径上最多只有一种点权出现了奇数次。
点权>=0。
对于询问2,因为保证路径上最多只有一种点权出现了奇数次,所以将路径上的值异或起来,如果不为0则该值就是答案。如果为0,有两种可能,一种是所有权值都出现了偶数次,或者权值0出现了奇数次,为了避免这种情况,我们把所有权值都+1,最后输出的时候-1即可。
裸的树剖,然而我这个沙茶调到早上才发现变量忘了初始化。
还有就是别忘了手工栈或者栈外挂。
#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> #include <climits> #include <vector> #define lch rt << 1 #define rch rt << 1 | 1 #define lson l, mid, lch #define rson mid + 1, r, rch using namespace std; const int MAXN = 100005; int n, q; int value[MAXN]; vector<int> edges[MAXN]; int tot = 0; int siz[MAXN], deep[MAXN], max_son[MAXN]; int mark[MAXN], top[MAXN]; int fa[MAXN]; void dfs_size(int x, int dep) { deep[x] = dep; max_son[x] = 0; siz[x] = 1; for (int i = 0; i < edges[x].size(); i++) { int nex = edges[x][i]; if (nex == fa[x]) continue; fa[nex] = x; dfs_size(nex, dep + 1); siz[x] += siz[nex]; if (!max_son[x] || siz[nex] > siz[max_son[x]]) max_son[x] = nex; } } int _num = 0; void dfs_remark(int x, int topx) { top[x] = topx; mark[x] = ++_num; if (max_son[x]) dfs_remark(max_son[x], topx); for (int i = 0; i < edges[x].size(); i++) { int nex = edges[x][i]; if (nex == fa[x]) continue; if (max_son[x] != nex) dfs_remark(nex, nex); } } int sum[MAXN << 2]; void push_up(int rt) { sum[rt] = sum[lch] ^ sum[rch]; } void build_tree(int l, int r, int rt) { int mid = l + r >> 1; sum[rt] = 0; if (l == r) return; build_tree(lson); build_tree(rson); } void insert(int l, int r, int rt, int id, int val) { if (l == r) { sum[rt] = val; return; } int mid = l + r >> 1; if (id <= mid) insert(lson, id, val); else insert(rson, id, val); push_up(rt); } int query(int l, int r, int rt, int L, int R) { if (L <= l && R >= r) return sum[rt]; int mid = l + r >> 1; int sum = 0; if (L <= mid) { sum ^= query(lson, L, R); } if (mid < R) { sum ^= query(rson, L, R); } return sum; } int solve(int a, int b) { int f1 = top[a], f2 = top; int ans = 0; while (f1 != f2) { if (deep[f1] < deep[f2]) { swap(f1, f2); swap(a, b); } ans ^= query(1, n, 1, mark[f1], mark[a]); a = fa[f1]; f1 = top[a]; } if (deep[a] > deep[b]) swap(a, b); return ans ^ query(1, n, 1, mark[a], mark[b]); } int T; int main() { scanf("%d", &T); while (T--) { scanf("%d %d", &n, &q); int a, b; for (int i = 1; i <= n; i++) edges[i].clear(); tot = _num = 0; for (int i = 1; i < n; i++) { scanf("%d %d", &a, &b); edges[a].push_back(b); edges[b].push_back(a); } for (int i = 1; i <= n; i++) { scanf("%d", &value[i]); value[i]++; } dfs_size(1, 1); dfs_remark(1, 1); build_tree(1, n, 1); for (int i = 1; i <= n; i++) insert(1, n, 1, mark[i], value[i]); int op, x, y; for (int i = 0; i < q; i++) { scanf("%d", &op); scanf("%d %d", &x, &y); if (!op) { y++; insert(1, n, 1, mark[x], y); } else { int ans = solve(x, y); cout << ans - 1 << endl; } } } return 0; }
[b]1004.Dylans loves polynomial
Dylans有N个平面直角坐标系的点对(Xi,Yi)。同时还有Q个询问。每次的询问给定三个参数(L,R,x)。
他的任务是用L∼R的这些点构成(R−L)阶多项式来拟合这些点。
为了检验他的多项式,他需要把x带入后计算出多项式的值(即y)。
因为这些多项式系数和点对坐标可能都比较大,所有运算都在模1000000007域下进行。
点对的大小和x均为小于等于250000的正整数。且每一个x都互不相同。
2≤N≤3000,1≤Q≤3000。
1≤L,R≤N且R>L
裸的牛顿插值。。
但是如果直接算逆元的话会T,我们发现坐标范围是250000,于是可以先把0~250000的逆元预处理出来,这样就不会T。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const long long MOD = 1000000007; long long read() { long long x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int n, q; long long x[3005], y[3005]; long long c[3005][3005]; long long inv[250005]; long long powmod(long long a, long long b) { long long ans = 1; while (b) { if (b & 1) ans = ans * a % MOD; a = a * a % MOD; b >>= 1; } return ans; } void init() { for (int i = 0; i <= 250000; i++) inv[i] = powmod(i, MOD - 2); for (int j = 0; j < n; j++) { for (int i = 0; i + j < n; i++) { if (!j) c[i][i + j] = y[i]; else if (x[i + j] > x[i]) c[i][i + j] = (c[i + 1][i + j] - c[i][i + j - 1] + MOD) % MOD * inv[x[i + j] - x[i]] % MOD; else c[i][i + j] = (c[i][i + j - 1] - c[i + 1][i + j] + MOD) % MOD * inv[-x[i + j] + x[i]] % MOD; } } } long long calc(int l, int r, long long xx) { long long ans = 0, t = 1; for (int i = l; i <= r; i++) { ans = (ans + c[l][i] * t % MOD) % MOD; t = t * (xx - x[i] + MOD) % MOD; } return ans; } int main() { n = read(); for (int i = 0; i < n; i++) { x[i] = read(); y[i] = read(); } init(); q = read(); int l, r, xx; for (int i = 0; i < q; i++) { l = read(); r = read(); xx = read(); printf("%I64d\n", calc(l - 1, r - 1, xx)); } return 0; }
相关文章推荐
- Deutsch lernen (10)
- Triangle
- Bootstrap开发
- Deutsch lernen (09)
- Deutsch lernen (08)
- 【Leetcode】【Medium】Linked List Cycle II
- CUDA Libraries简介
- linux环境下安装redis扩展
- LINUX环境下SVN安装与配置(利用钩子同步开发环境与测试环境)
- 笔记-Microsoft SQL Server 2008技术内幕:T-SQL语言基础-05 表表达式
- Deutsch lernen (07)
- Contains Duplicate III
- 加载网络图片HttpClient
- 【群视频】笔记 - 2015.06.03
- win7安装Infragistics NetAdvantage,报错
- leetcode-217-Contains Duplicate
- C++ stderr/stdout 重定向到文件
- ubuntu 安装 google Gtest
- BOZJ2733 [HNOI2012]永无乡(Treap+启发式合并)
- 委托