20170122 机房『练习赛』
科学家不是依赖于个人的思想,而是综合了几千人的智慧,所有的人想一个问题,并且每人做它的部分工作,添加到正建立起来的伟大知识大厦之中。
—— 卢瑟福
我热爱生活,我是一名快速成长的OIer
目录:
T1 distance
第一题AC,LAC。可倍增,亦可DFS序。本人当时构造数据很恼火,查了了半天错才发现是数据有诈(谁家树上有环!)。其实,树很好构造,第一条边为2和1,第二条边为3和2或1,第三条边为4和3或2或1。。。第
n
条边为
P.S.:NOIP提高组2016 D1 T2 天天爱跑步,很像,很像。。。
时间复杂度:
O(nlogn+Qlogn)
#define PROGRAM_NAME "distance"
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct IO {
IO() {
freopen(PROGRAM_NAME".in","r",stdin);
freopen(PROGRAM_NAME".out","w",stdout);
}
~IO() {
fclose(stdin);
fclose(stdout);
}
}hyz;
template<class TE> inline void readin(TE &res) {
char ch;int flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
res=ch-48;
while((ch=getchar())>='0' && ch<='9') res=(res<<1)+(res<<3)+ch-48;
res*=flag;
}
const int MAXN = 100000 + 10000;
const int MAXM = MAXN + MAXN;
const int MAXP = 20;
struct Edge {
int v, w, next;
}t[MAXM];
int head[MAXN], num=0;
inline void insert( int u, int v, int w ) {
t[++num].v = v;
t[num].w = w;
t[num].next = head[u];
head[u] = num;
}
int anc[MAXN][MAXP+1], deep[MAXN], price[MAXN*2][MAXP+1];
void dfs( int u, int f ) {
anc[u][0] = f;
for (int p=1; p<=MAXP; p++)
{
anc[u][p] = anc[anc[u][p-1]][p-1];
price[u][p] = price[u][p-1]+price[anc[u][p-1]][p-1];
}
for (int i=head[u]; i; i=t[i].next)
{
int v = t[i].v;
if (v==f) continue;
deep[v] = deep[u] + 1;
price[v][0] = t[i].w;
dfs( v, u );
}
}
int N;
void init() {
memset(price,0,sizeof(price));
readin( N );
for (int i=1; i<=N-1; i++) {
int u, v, w;
readin( u );
readin( v );
readin( w );
insert( u, v, w );
insert( v, u, w );
}
dfs( 1, 1 );
}
int LCA( int u, int v ) {
int dis=0;
if (deep[u]<deep[v]) swap(u,v);
int t = deep[u] - deep[v];
for (int p=0; p<=MAXP; t>>=1,p++) if (t&1) {
dis = dis + price[u][p];
u = anc[u][p];
}
if (u==v) return dis;
for (int p=MAXP; anc[u][0]!=anc[v][0]; p--) if (anc[u][p]!=anc[v][p]) {
dis = dis + price[v][p] + price[u][p];
u = anc[u][p];
v = anc[v][p];
}
return dis + price[u][0] + price[v][0];
}
void solve(){
int Q;
readin(Q);
while (Q--) {
int u, v;
readin(u);
readin(v);
printf("%d\n",LCA(u,v));
}
}
int main() {
init();
solve();
return 0;
}
T2 redpacket
第二题AC,线段树。子树修改,单点查询,区间查询。同T1,被自造数据坑了。。。
时间复杂度:
O(nlogn+Qlogn)
#define PROGRAM_NAME "redpacket"
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct IO {
IO() {
freopen(PROGRAM_NAME".in","r",stdin);
freopen(PROGRAM_NAME".out","w",stdout);
}
~IO() {
fclose(stdin);
fclose(stdout);
}
}hyz;
template<class TE> inline void readin(TE &res) {
char ch;int flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
res=ch-48;
while ((ch=getchar())>='0' && ch<='9') res=(res<<1)+(res<<3)+ch-48;
res*=flag;
}
const int MAXN = 100000 + 1000;
const int MAXM = MAXN + MAXN;
struct Edge {
int v, next;
}t[MAXM];
int head[MAXN], num = 0;
inline void insert( int u, int v ) {
t[++num].v = v;
t[num].next = head[u];
head[u] = num;
}
int in[MAXN], out[MAXN], INDEX = 0;
bool vis[MAXN];
void dfs( int u, int f ) {
in[u] = ++INDEX;
for (int i=head[u]; i; i=t[i].next) if (!vis[t[i].v]){
int v = t[i].v;
vis[v]=1;
if (v==f) continue;
dfs( v, u );
}
out[u] = INDEX;
}
int N;
void init(){
readin( N );
for (int i=1; i<=N-1; i++) {
int u, v;
readin( u );
readin( v );
insert( u, v );
insert( v, u );
}
dfs( 1, 1 );
}
struct Node {
long long sum, flag;
Node *rs, *ls;
Node() {
sum = 0;
flag = 0;
rs = NULL;
ls = NULL;
}
void pushdown( int lf, int rg ) {
int mid = (lf+rg)>>1;
ls->sum += (long long)(mid-lf+1)*flag;
rs->sum += (long long)(rg-mid)*flag;
ls->flag += flag;
rs->flag += flag;
flag = 0;
}
}pool[MAXN*2+1000], *tail=pool, *root;
Node *build(int lf, int rg) {
Node *nd = ++tail;
if (lf==rg) {
nd->sum = 0;
}else {
int mid = (lf+rg)>>1;
nd->ls = build( lf, mid );
nd->rs = build( mid+1, rg);
nd->sum = 0;
}
return nd;
}
void modify(struct Node *nd, int lf, int rg, int L, int R, long long val) {
if (L<=lf && rg<=R) {
nd->sum += (long long)(rg-lf+1)*val;
nd->flag += val;
}else {
int mid = (lf+rg)>>1;
nd->pushdown(lf,rg);
if (L<=mid) modify(nd->ls,lf,mid,L,R,val);
if (R>mid) modify(nd->rs,mid+1,rg,L,R,val);
nd->sum = nd->ls->sum + nd->rs->sum;
}
}
long long query(struct Node *nd, int lf, int rg, int L, int R) {
if (L<=lf && rg<=R) {
return nd->sum;
}else {
int mid = (lf+rg)>>1;
nd->pushdown(lf,rg);
long long td = 0;
if (L<=mid) td += query(nd->ls,lf,mid,L,R);
if (R>mid) td += query(nd->rs,mid+1,rg,L,R);
return td;
}
}
long long query(struct Node *nd, int lf, int rg, int pos) {
if (lf==rg) {
return nd->sum;
}else {
int mid = (lf+rg)>>1;
nd->pushdown(lf,rg);
if (pos<=mid) return query(nd->ls,lf,mid,pos);
else return query(nd->rs,mid+1,rg,pos);
}
}
void solve(){
root = build( 1, N );
int Q;
readin( Q );
while (Q--) {
char ss[100];
int u;
long long w;
scanf( "%s", ss );
if (ss[0]=='g') {
readin(u);
readin(w);
modify(root,1,N,in[u],out[u],w);
}else if (ss[0]=='s') {
readin(u);
cout << query(root,1,N,in[u]) << endl;
}else {
readin(u);
cout << query(root,1,N,in[u],out[u]) << endl;
}
}
}
int main()
{
init();
solve();
return 0;
}
T3 kth
第三题AC,值域线段树。类似桶排,添加删除(单点修改),询问全区间第K小(单点查询)。
时间复杂度:
O(nlogn+Qlogn)
#define PROGRAM_NAME "kth"
#include <cstdio>
#include <algorithm>
using namespace std;
struct IO {
IO() {
freopen(PROGRAM_NAME".in","r",stdin);
freopen(PROGRAM_NAME".out","w",stdout);
}
~IO() {
fclose(stdin);
fclose(stdout);
}
}hyz;
template<class TE> inline void readin(TE &res) {
char ch;int flag=1;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
res=ch-48;
while ((ch=getchar())>='0' && ch<='9') res=(res<<1)+(res<<3)+ch-48;
res*=flag;
}
const int MAXN = 100000 + 1000;
int lb, rb, aa[MAXN];
void init(){
readin( lb );
readin( rb );
for (int i=1; i<=rb-lb+1; i++) readin(aa[i]);
}
struct Node {
int siz;
Node *ls, *rs;
Node() {
siz = 0;
ls = NULL;
rs = NULL;
}
}pool[MAXN*2+1000], *tail=pool, *root;
Node *build(int lf, int rg) {
Node *nd = ++tail;
if (lf==rg) {
nd->siz = aa[lf-lb+1];
} else {
int mid = (lf+rg)>>1;
nd->ls = build(lf,mid);
nd->rs = build(mid+1,rg);
nd->siz = nd->ls->siz + nd->rs->siz;
}
return nd;
}
void modify(struct Node *nd, int lf, int rg, int pos, int val) {
if (lf==rg) {
nd->siz+=val;
if (nd->siz<0) nd->siz=0;
} else {
int mid = (lf+rg)>>1;
if (pos<=mid) modify(nd->ls,lf,mid,pos,val);
else modify(nd->rs,mid+1,rg,pos,val);
nd->siz=nd->ls->siz+nd->rs->siz;
}
}
int query(struct Node *nd, int lf, int rg, int k) {
if (lf==rg) {
return lf;
} else {
int mid = (lf+rg)>>1;
if (k<=nd->ls->siz) return query(nd->ls,lf,mid,k);
else return query(nd->rs,mid+1,rg,k-nd->ls->siz);
}
}
void solve(){
root = build(lb,rb);
int Q;
readin(Q);
while (Q--) {
char ss[100];
int x, k;
scanf( "%s", ss );
if (ss[0]=='a') {
readin(x);
modify(root,lb,rb,x,+1);
} else if (ss[0]=='d') {
readin(x);
modify(root,lb,rb,x,-1);
} else {
readin(k);
printf("%d\n",query(root,lb,rb,k));
}
}
}
int main()
{
init();
solve();
return 0;
}
经验与教训
这一次AK,随同刘凯淇和std。simpsonk,呵呵。叶余非第二题爆了,可引以为戒。
附录: 大神与非大神的blog
Websites | Belonging to | P.S. |
---|---|---|
idy002 - 丁尧尧 | cnblogs | 高新的荣耀 |
lflame - 杨雅儒 | lofter | OMG |
yjq_naive - 杨景钦 | lofter | 国家集训队选手 |
阿波罗2003 - yyf | cnblogs | 萌萌的小东西 |
mcfx - wsq | 自建 | 必成大器 |
hzwer - 黄学长 | 自建 | 无需多言 |
董的博客 | 自建 | 入门教程必读 |
林荫高16级信竞公共博客 | CSDN | 强! |
deadshotz - 程sz | cnblogs | 就是个高二的 |
lemonoil - lmy | CSDN | 有待追赶 |
lemonoil - lmy | cnblogs | 小号 |
Doggu - gyk | CSDN | 呵呵 |
Doggu - gyk | cnblogs | 精美小号 |
maverickfw - wyy | CSDN | FAT |