51Nod 算法马拉松24
来源:互联网 发布:iosapp开发需要mac 编辑:程序博客网 时间:2024/04/29 05:15
A : 构造
B : 状压DP
C : 构造
D : 线段树或平衡树
E : 树链剖分+线段树
F : Unfinished
A 1804 小C的多边形
强行猜了一个结论,试了一下小数据发现没问题,那就假装没问题吧……就是外面一圈1~n-1,里面把1插在n-2和n-1之间,其他的顺次递推。
本题考察输出优化的使用。
#include<cstdio>using namespace std;namespace runzhe2000{ int n, last = 1, sum, tot; char buff[20000000]; void print_char(char c){buff[++tot] = c;} void print_int(int x) { if(x>9)print_int(x/10); buff[++tot] = (x%10+'0'); } void print_close(){puts(buff+1);} void main() { scanf("%d",&n); n--; if(~n&1){puts("0");return;} sum = 3*(n+1)>>1; for(int i = 1; i <= n; i++) print_int(i),print_char(' '); print_char('\n'); for(int i = 1; i <= n; i++) print_int(last = sum - ((i-1+n)%n?(i-1+n)%n:n) - last),print_char(' '); print_close(); }}int main(){ runzhe2000::main();}
B 1779 逆序对统计
按数字从小到大做,记
这样是
#include<cstdio>#include<cstring>#include<algorithm>#define N 22#define M 105#define cmax(u,v) ((u)<(v)?(u)=(v):0)using namespace std;namespace runzhe2000{ const int INF = 1<<29; int n, m, f[2][1<<N], cur, popcount[1<<N], happy; void main() { happy = scanf("%d%d",&n,&m); for(int i = 0; i < (1<<n); i++) popcount[i] = __builtin_popcount(i); memset(f, -63, sizeof(f)); f[cur][0] = 0; for(int i = 1, pos; i <= m; i++, cur ^= 1) { happy = scanf("%d",&pos); int *fc = f[cur], *fcc = f[cur^1], p = 1<<(pos-1); for(int s = (1<<n)-1; ~s; s--) { int v = fc[s]; cmax(fcc[s], v); if(~s&p) { int ss = s | p, tmp = v + popcount[s>>pos]; cmax(fcc[ss], tmp); } fc[s] = -INF; } } printf("%d\n",f[cur][(1<<n)-1]); }}int main(){ runzhe2000::main();}
C 1851 俄罗斯方块
看上去好像非常复杂,实际上用这些方块已经能弄出很多图形了……首先一个显然的结论是奇数个1不可能完成,以下讨论均默认偶数个1。
考虑我们用一个T形的和一个Z形的即可构出如下的反转方案
100
100
同样,用一个L形的和一个Z形的即可构出如下的反转方案
010
100
也就是说,如果不考虑边界,我们可以把一个1直接挪到它的八个邻点之一。理论上如果边界无限远则任意一种局面都可行。考虑边界是怎样的,不妨设n<=m,易证如果n>=2并且m>=3就一定可以。考虑更小的边界,对于2×2的暴力判一下即可。剩下的,对于n=1的情况手动用I形的覆盖一下即可……
#include<cstdio>#include<algorithm>#define N 10000005using namespace std;namespace runzhe2000{ int read01(){char c = getchar(); for(; c != '0' && c != '1'; c = getchar()); return c - '0';} int a[N], n, m, T; void main() { scanf("%d",&T); for(; T--; ) { int cnt = 0, siz = 0; scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) cnt += (a[++siz] = read01()); if(cnt&1) puts("No"); else { if((n>=2 && m>=3) || (m>=2 && n>=3)) puts("Yes"); else if(n == 2 && m == 2) puts((cnt&&cnt!=4)?"No":"Yes"); else { n > m ? m = n: 0; if(m <= 3) puts(cnt?"No":"Yes"); else { for(int i = 1, ii = m-3; i <= ii; i++) if(a[i]) { cnt -= a[i] + a[i+1] + a[i+2] + a[i+3]; a[i] ^= 1; a[i+1] ^= 1; a[i+2] ^= 1; a[i+3] ^= 1; cnt += a[i] + a[i+1] + a[i+2] + a[i+3]; } puts(cnt?"No":"Yes"); } } } } }}int main(){ runzhe2000::main();}
D 1680 区间求和
考虑已经知道区间[l,r]的答案,现在在r后面加入a[i] (r+1=i),区间[l,i]的答案会变成什么。记区间[l,r]的答案为sum,c表示[l,r]里面比a[i]小的数的个数,s表示[l,r]里面比a[i]大的数的和,则推一下发现[l,i]的答案是 sum+(c+1)*a[i]+s。
推广下去,考虑已经知道了区间[l,r]以及其所有子区间的答案,同样加入一个a[i],考虑区间[l,i]以及其所有子区间的答案会变成什么。同样推一下得到答案是:
做法口胡完了QAQ。实际上对于后者,要维护的信息还是很多,比如轻边的子树内黑点个数,区间奇数层取反完值会变化多少等等……
不得不说51Nod的评测机是真的快,本机极限数据跑了差不多10s,我还他以为卡两个log。正在绝望之际,交一发,1.5s就过出来了……其实大概是本机太慢了吧,这个电脑连打字都越来越卡了……
#include<cstdio>#define N 200005using namespace std;namespace runzhe2000{ typedef long long ll; int read() { int r = 0; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()); for(; c >='0' && c <='9'; r = r*10+c-'0', c = getchar()); return r; } int n, m, last[N], ecnt, c[N], top[N], siz[N], fa[N], son[N], dep[N], beg[N], rebeg[N], end[N], timer; struct edge{int next, to;}e[N<<1]; void addedge(int a, int b){e[++ecnt] = (edge){last[a], b}; last[a] = ecnt;} void dfs1(int x) { dep[x] = dep[fa[x]] + 1; siz[x] = 1; for(int i = last[x]; i; i = e[i].next) {int y = e[i].to; if(y == fa[x]) continue;fa[y] = x; dfs1(y); siz[x] += siz[y]; siz[y] > siz[son[x]] ? son[x] = y : 0;} } void dfs2(int x) { rebeg[beg[x] = ++timer] = x; top[x] = son[fa[x]]==x?top[fa[x]]:x; if(son[x]) dfs2(son[x]); for(int i = last[x]; i; i = e[i].next){int y = e[i].to; if(y == son[x] || y == fa[x]) continue;dfs2(y);}end[x] = timer; } struct seg { int siz[2], siz_bla[2], rev[2]; ll mod[2], val; }t1[N*5], t2[N*5]; /***************************************************************************************************************/ void pushup1(int x) { seg *ls = &t1[x<<1], *rs = &t1[x<<1|1]; for(int i = 0; i != 2; i++) { t1[x].siz[i] = ls->siz[i] + rs->siz[i]; t1[x].siz_bla[i] = ls->siz_bla[i] + rs->siz_bla[i]; } } void pushdown1(int x) { seg *ls = &t1[x<<1], *rs = &t1[x<<1|1]; for(int i = 0; i != 2; i++) if(t1[x].rev[i]) { ls->siz_bla[i] = ls->siz[i] - ls->siz_bla[i], rs->siz_bla[i] = rs->siz[i] - rs->siz_bla[i]; ls->rev[i] ^= 1, rs->rev[i] ^= 1, t1[x].rev[i] = 0; } } void build1(int x, int l, int r) { t1[x].rev[0] = t1[x].rev[1] = 0; if(l == r) { int id = rebeg[l], d = (dep[id]&1); t1[x].siz[d] = 1; t1[x].siz[!d] = 0; t1[x].siz_bla[d] = c[id]; t1[x].siz_bla[!d] = 0; return; } int mid = (l+r)>>1; build1(x<<1,l,mid); build1(x<<1|1,mid+1,r); pushup1(x); } int query1_siz_bla(int x, int l, int r, int ql, int qr, int d) { if(ql <= l && r <= qr) return t1[x].siz_bla[d]; int mid = (l+r)>>1, ret = 0; pushdown1(x); if(ql <= mid) ret += query1_siz_bla(x<<1,l,mid,ql,qr,d); if(mid<qr) ret += query1_siz_bla(x<<1|1,mid+1,r,ql,qr,d); return ret; } int query1_siz_bla(int x, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) return t1[x].siz_bla[0]+t1[x].siz_bla[1]; int mid = (l+r)>>1, ret = 0; pushdown1(x); if(ql <= mid) ret += query1_siz_bla(x<<1,l,mid,ql,qr); if(mid<qr) ret += query1_siz_bla(x<<1|1,mid+1,r,ql,qr); return ret; } int query1_siz(int x, int l, int r, int ql, int qr, int d) { if(ql <= l && r <= qr) return t1[x].siz[d]; int mid = (l+r)>>1, ret = 0; pushdown1(x); if(ql <= mid) ret += query1_siz(x<<1,l,mid,ql,qr,d); if(mid<qr) ret += query1_siz(x<<1|1,mid+1,r,ql,qr,d); return ret; } void modi1(int x, int l, int r, int ql, int qr, int d) { if(ql <= l && r <= qr) {t1[x].rev[d] ^= 1; t1[x].siz_bla[d] = t1[x].siz[d] - t1[x].siz_bla[d]; return;} int mid = (l+r)>>1; pushdown1(x); if(ql <= mid) modi1(x<<1,l,mid,ql,qr,d); if(mid < qr) modi1(x<<1|1,mid+1,r,ql,qr,d); pushup1(x); } /***************************************************************************************************************/ void pushup2(int x) { seg *ls = &t2[x<<1], *rs = &t2[x<<1|1]; for(int i = 0; i != 2; i++) { t2[x].siz[i] = ls->siz[i] + rs->siz[i]; t2[x].siz_bla[i] = ls->siz_bla[i] + rs->siz_bla[i]; t2[x].mod[i] = ls->mod[i] + rs->mod[i]; t2[x].val = ls->val + rs->val; } } void pushdown2(int x) { seg *ls = &t2[x<<1], *rs = &t2[x<<1|1]; for(int i = 0; i != 2; i++) if(t2[x].rev[i]) { ls->siz_bla[i] = ls->siz[i] - ls->siz_bla[i], rs->siz_bla[i] = rs->siz[i] - rs->siz_bla[i]; ls->rev[i] ^= 1, rs->rev[i] ^= 1, t2[x].rev[i] = 0; ls->val += ls->mod[i], rs->val += rs->mod[i]; ls->mod[i] *= -1, rs->mod[i] *= -1; } } void build2(int x, int l, int r) { t2[x].rev[0] = t2[x].rev[1] = 0; if(l == r) { int id = rebeg[l], d = (dep[id]&1); t2[x].siz[d] = 1; t2[x].siz[!d] = 0; t2[x].siz_bla[d] = query1_siz_bla(1,1,n,beg[id],beg[id]); t2[x].siz_bla[!d] = 0; for(int i = last[id]; i; i = e[i].next) { int y = e[i].to; if(y == son[id] || y == fa[id]) continue; t2[x].siz[d] += query1_siz(1,1,n,beg[y],end[y],d); t2[x].siz[!d] += query1_siz(1,1,n,beg[y],end[y],!d); t2[x].siz_bla[d] += query1_siz_bla(1,1,n,beg[y],end[y],d); t2[x].siz_bla[!d] += query1_siz_bla(1,1,n,beg[y],end[y],!d); } t2[x].mod[d] = (t2[x].siz[d] - 2ll * t2[x].siz_bla[d]) * id; t2[x].mod[!d] = (t2[x].siz[!d] - 2ll * t2[x].siz_bla[!d]) * id; t2[x].val = (ll)(t2[x].siz_bla[d] + t2[x].siz_bla[!d]) * id; return; } int mid = (l+r)>>1; build2(x<<1,l,mid); build2(x<<1|1,mid+1,r); pushup2(x); } ll query2(int x, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) return t2[x].val; int mid = (l+r)>>1; ll ret = 0; pushdown2(x); if(ql <= mid) ret += query2(x<<1,l,mid,ql,qr); if(mid < qr) ret += query2(x<<1|1,mid+1,r,ql,qr); return ret; } void modi2(int x, int l, int r, int ql, int qr, int d) { if(ql <= l && r <= qr) { t2[x].siz_bla[d] = t2[x].siz[d] - t2[x].siz_bla[d]; t2[x].rev[d] ^= 1; t2[x].val += t2[x].mod[d]; t2[x].mod[d] *= -1; return; } int mid = (l+r)>>1; pushdown2(x); if(ql <= mid) modi2(x<<1,l,mid,ql,qr,d); if(mid < qr) modi2(x<<1|1,mid+1,r,ql,qr,d); pushup2(x); } void update2(int x, int l, int r, int p) { if(l == r) {build2(x,l,r); return;} int mid = (l+r)>>1; pushdown2(x); if(p <= mid) update2(x<<1,l,mid,p); else update2(x<<1|1,mid+1,r,p); pushup2(x); } /***************************************************************************************************************/ void main() { n = read(), m = read(); for(int i = 1; i <= n; i++) c[i] = read(); for(int i = 1, a, b; i < n; i++) addedge(a = read(), b = read()), addedge(b,a); dfs1(1); dfs2(1); build1(1,1,n); build2(1,1,n); for(int t = 1, op, x; t <= m; t++) { op = read(), x = read(); if(op == 1) { int d = (dep[x]&1)^1; modi1(1,1,n,beg[x],end[x],d); for(int tmp = top[x]; fa[tmp]; tmp = top[fa[tmp]]) update2(1,1,n,beg[fa[tmp]]); modi2(1,1,n,beg[x],end[x],d); } else if(op == 2) { int d = (dep[x]&1); modi1(1,1,n,beg[x],beg[x],d); update2(1,1,n,beg[x]); for(int tmp = top[x]; fa[tmp]; tmp = top[fa[tmp]]) update2(1,1,n,beg[fa[tmp]]); } else { ll ans = (ll)x * query1_siz_bla(1,1,n,beg[x],end[x]); for(int tmp = x, son = x; tmp; tmp = fa[son = top[tmp]]) { if(tmp != x) ans += (ll)tmp * (query1_siz_bla(1,1,n,beg[tmp],end[tmp]) - query1_siz_bla(1,1,n,beg[son],end[son])); if(tmp != top[tmp]) ans += query2(1,1,n,beg[top[tmp]],beg[tmp]-1); } printf("%lld\n",ans); } } }}int main(){ runzhe2000::main();}
- 51Nod 算法马拉松24
- 51nod 算法马拉松12
- 51nod算法马拉松20
- 51Nod 算法马拉松23
- 51nod算法马拉松25
- 51nod 算法马拉松 集合计数
- 51nod 算法马拉松11 D 计算
- 51nod 算法马拉松12 逛街(treap)
- [51nod]算法马拉松18 总结
- 51nod算法马拉松18总结
- 51nod 算法马拉松19 A P1674
- 51nod算法马拉松19总结
- 【51nod】算法马拉松19 总结
- 51nod算法马拉松20总结
- 51nod算法马拉松21总结
- 51NOD算法马拉松 七星剑 【dp】
- 51nod算法马拉松22总结
- 51nod算法马拉松23划水记
- 【JavaScript】(5)匿名函数的定义方式、变量的作用域(局部变量,全局变量)
- 剑指offer-面试题59-对称的二叉树
- 二分查找的递归和非递归实现
- Android studio使用技巧(二:国际化以及代码重构)
- FireBreath框架:NPAPI浏览器插件开发
- 51Nod 算法马拉松24
- C语言--格式化输入/输出函数(printf/scanf,fprintf/fscanf,sprintf,sscanf)
- 基础简单的数据结构-C语言-动态链表
- json格式的日期反序列化方法
- com.android.dex.DexIndexOverflowException: Cannot merge new index 65730 into a non-jumbo instructio
- Spring 事务的传播行为
- shell之文本查找
- 整数划分的递归实现算法
- 【聚类论文笔记】Cluster Ensembles – A Knowledge Reuse Framework for Combining Multiple Partitions