20170122 机房『练习赛』

20170122 机房『练习赛』

科学家不是依赖于个人的思想,而是综合了几千人的智慧,所有的人想一个问题,并且每人做它的部分工作,添加到正建立起来的伟大知识大厦之中。
—— 卢瑟福

我热爱生活,我是一名快速成长的OIer

目录:

T1 distance

这里写图片描述
第一题AC,LAC。可倍增,亦可DFS序。本人当时构造数据很恼火,查了了半天错才发现是数据有诈(谁家树上有环!)。其实,树很好构造,第一条边为2和1,第二条边为3和2或1,第三条边为4和3或2或1。。。第 n 条边为(n+1) (rand() % n+1)
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,随同刘凯淇stdsimpsonk,呵呵。叶余非第二题爆了,可引以为戒。

附录: 大神与非大神的blog

WebsitesBelonging toP.S.
idy002 - 丁尧尧cnblogs高新的荣耀
lflame - 杨雅儒lofterOMG
yjq_naive - 杨景钦lofter国家集训队选手
阿波罗2003 - yyfcnblogs萌萌的小东西
mcfx - wsq自建必成大器
hzwer - 黄学长自建无需多言
董的博客自建入门教程必读
林荫高16级信竞公共博客CSDN强!
deadshotz - 程szcnblogs就是个高二的
lemonoil - lmyCSDN有待追赶
lemonoil - lmycnblogs小号
Doggu - gykCSDN呵呵
Doggu - gykcnblogs精美小号
maverickfw - wyyCSDNFAT
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值