【浮*光】#省选真题# [SCOI2015]

 

就比较随性的记录一下啦啦啦啦啦啦啦 . . . . . .  

 

T1:【p4155】国旗计划 // 贪心 + 倍增

#include <cmath>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

/*【p4155】国旗计划 // 贪心 + 倍增 */

void reads(uint &x){ //读入优化(正负整数)
    uint fx_=1;x=0;char ch_=getchar();
    while(ch_<'0'||ch_>'9'){if(ch_=='-')fx_=-1;ch_=getchar();}
    while(ch_>='0'&&ch_<='9'){x=x*10+ch_-'0';ch_=getchar();}
    x*=fx_; //正负号
}

const uint N=200019;

struct Seg{ uint l,r,id; //记录线段(区间),并不是segment_tree
  Seg(uint a=0,uint b=0,uint c=0):l(a),r(b),id(c){} //↓↓按左端点排序(区间无重叠)
  friend bool operator < (const Seg &a,const Seg &b){return a.l<b.l;} }seg[N<<1];

int mul[19][N<<1],ans[N]; uint n,m;

void Init(){
    sort(seg+1,seg+1+2*n); int pit=0; seg[2*n+1]=Seg(-1,-1); //设定外部终点
    for(int i=1;i<=2*n;i++) //维护一个指针,假如指针指向区间与当前区间有交集,就让指针右移
     //不断重复至某个与当前区间无交集的区间,那么它的前一个区间就是需要‘贪心’选取的区间
      { while(seg[pit+1].l<=seg[i].r) pit++; mul[0][i]=pit; }
    for(int j=1;j<=18;j++) for(int i=1;i<=2*n;i++) mul[j][i]=mul[j-1][mul[j-1][i]];
    seg[0]=Seg(-1,-1); // ↑↑ 倍增记录相关选择过程,并设置外部起点
}

int main(){
    reads(n),reads(m);
    for(int i=1;i<=n;i++){
        uint l,r; reads(l),reads(r);
        if(l<=r) seg[i]=Seg(l,r,i),seg[n+i]=Seg(m+l,m+r);
        else seg[i]=Seg(l,m+r,i),seg[n+i]=Seg(m+l,m*2+r);
    } Init(); //设置起点终点、求倍增区间
    for(int i=1;i<=2*n;i++){ if(!seg[i].id) continue;
        int pit=i,res=2; for(int j=18;j>=0;j--)
            if(seg[mul[j][pit]].r-seg[i].l<m) pit=mul[j][pit],res+=1<<j;
        ans[seg[i].id]=res; //记录此时需要的选择个数res
    } for(int i=1;i<=n;i++) cout<<ans[i]<<" "; cout<<endl;
}
View Code

 

T2:【p4216】情报传递 // 树剖 + 主席树/线段树

#include <cmath>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

/*【p4216】情报传递 // 树剖 + 主席树/线段树 */

/*【分析】将每个情报员开始搜集情报的时刻设为它的权值c。
对于一个始终没有搜集情报的人,权值设为Q(询问的个数)。
对于t时刻的询问,就转化为询问路径上比t-c小的值有多少个。 */

void reads(int &x){ //读入优化(正负整数)
    int fx_=1;x=0;char ch_=getchar();
    while(ch_<'0'||ch_>'9'){if(ch_=='-')fx_=-1;ch_=getchar();}
    while(ch_>='0'&&ch_<='9'){x=x*10+ch_-'0';ch_=getchar();}
    x*=fx_; //正负号
}

#define lson (rt<<1)
#define rson (rt<<1|1)

const int maxn=200000+10;

int n,m,rt,head[maxn],ver[maxn<<1],nextt[maxn<<1],tot;

int top[maxn],dep[maxn],son[maxn],fa[maxn],siz[maxn],id[maxn],rev[maxn],tim;

vector<int> v[maxn<<2];

void update(int x,int C,int l,int r,int rt){
    v[rt].push_back(C); if(l==r) return ;
    int mid=(l+r)>>1; if(x<=mid) update(x,C,l,mid,lson);
    else update(x,C,mid+1,r,rson);
}

int query(int L,int R,int C,int l,int r,int rt){
    if(L<=l&&r<=R){
        vector<int>::iterator it=upper_bound(v[rt].begin(),v[rt].end(),C);
        return it-v[rt].begin(); //↑↑暴力二分查找
    } int mid=(l+r)>>1,ans=0; if(L<=mid) ans+=query(L,R,C,l,mid,lson);
    if(R>mid) ans+=query(L,R,C,mid+1,r,rson); return ans;
}

void add_(int x,int y){ ver[++tot]=y,nextt[tot]=head[x],head[x]=tot; }

void dfs1(int x,int fa_){
    siz[x]=1,fa[x]=fa_,dep[x]=dep[fa_]+1; 
    int maxson=-1; for(int i=head[x],y;i;i=nextt[i]){
        y=ver[i]; if(y==fa_) continue;
        dfs1(y,x),siz[x]+=siz[y];
        if(siz[y]>maxson) maxson=siz[y],son[x]=y;
    }
}

void dfs2(int x,int topf){
    id[x]=++tim,rev[tim]=x,top[x]=topf; if(son[x]) dfs2(son[x],topf);
    for(int i=head[x],y;i;i=nextt[i])
     { y=ver[i]; if(y==fa[x]||y==son[x]) continue; dfs2(y,y); }
}

inline void ask(int x,int y,int z){
    int ans1=0,ans2=0; while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y); ans1+=id[x]-id[top[x]]+1;
        ans2+=query(id[top[x]],id[x],z,1,n,1),x=fa[top[x]];
    } if(dep[x]>dep[y]) swap(x,y);
    ans1+=id[y]-id[x]+1,ans2+=query(id[x],id[y],z,1,n,1);
    printf("%d %d\n",ans1,ans2);
}

int main(){ 
    reads(n); for(int i=1,x;i<=n;i++)
     { reads(x); if(!x) rt=i; else add_(x,i); }
    dfs1(rt,0),dfs2(rt,rt); reads(m);
    for(int i=1,op,x,y,z;i<=m;i++){ reads(op),reads(x);
      if(op==1) reads(y),reads(z),ask(x,y,i-z-1); //查询可行性
      if(op==2) update(id[x],i,1,n,1); /* 修改x节点对应的权值 */ }
}
View Code

 

T3:【p4216】情报传递 // 树剖 + 主席树/线段树

posted @ 2019-03-19 15:30  花神&缘浅flora  阅读(128)  评论(0编辑  收藏  举报