zoukankan      html  css  js  c++  java
  • BZOJ3123: [Sdoi2013]森林

    3123: [Sdoi2013]森林

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 757  Solved: 279
    [Submit][Status]

    Description

    Input

    第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1≤testcase≤20。
    第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。第三行包含N个非负整数表示 N个节点上的权值。
     接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边, 接下来 T行,每行描述一个操作,格式为“Q x y k”或者“L x y ”,其含义见题目描述部分。

    Output

    对于每一个第一类操作,输出一个非负整数表示答案。 
     
     

    Sample Input

    1
    8 4 8
    1 1 2 2 3 3 4 4
    4 7
    1 8
    2 4
    2 1
    Q 8 7 3 Q 3 5 1
    Q 10 0 0
    L 5 4
    L 3 2 L 0 7
    Q 9 2 5 Q 6 1 6

    Sample Output

    2
    2
    1
    4
    2

    HINT



    对于第一个操作 Q 8 7 3,此时 lastans=0,所以真实操作为Q 8^0 7^0 3^0,也即Q 8 7 3。点8到点7的路径上一共有5个点,其权值为4 1 1 2 4。这些权值中,第三小的为 2,输出 2,lastans变为2。对于第二个操作 Q 3 5 1 ,此时lastans=2,所以真实操作为Q 3^2 5^2 1^2 ,也即Q 1 7 3。点1到点7的路径上一共有4个点,其权值为 1 1 2 4 。这些权值中,第三小的为2,输出2,lastans变为 2。之后的操作类似。 

     

    Source

    题解:

    这题做得更苦逼。。。

    昨天下午写了2h,调了2h,一直RE,而且我数组都开到3000W了。。。

    然后各种输出中间结果(论不会用gdb的蒻是多么sb。。。)

    发现有一个询问WA了,导致^了之后超界了。

    然后开始找为什么WA。。。又是两节课。。。

    最后……最后……

    for1(i,18)if((1<<i)<=dep[x])f[x][i]=f[f[x][i-1]][i-1];else break;

    原来是这样写的,为了防止超时直接break

    然后发现有可能原来的数据没有清空!!!!!!!!!!!!!!!!!导致倍增的时候就。。。。。。

    然后……

       for1(i,18)f[x][i]=f[f[x][i-1]][i-1];

    改成这样,居然还WA!!!!!!!!!!

    我再改一下输入。。。A了。。。

    感觉被坑两次。。。

    代码:(我还想没说题解。。。)

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 200000+5
     26 
     27 #define maxm 30000000+5
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define mod 1000000007
     44 
     45 using namespace std;
     46 
     47 inline int read()
     48 
     49 {
     50 
     51     int x=0,f=1;char ch=getchar();
     52 
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54 
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56 
     57     return x*f;
     58 
     59 }
     60 int n,m,q,cnt,tot1,tot2,rt[maxn],head[maxn],a[maxn],b[maxn],c[maxn],d[maxn],dep[maxn];
     61 int s[maxn],fa[maxn],f[maxn][20],ls[maxm],rs[maxm],sum[maxm];
     62 struct edge{int go,next;}e[2*maxn];
     63 inline void insert(int x,int y)
     64 {
     65     e[++tot1]=(edge){y,head[x]};head[x]=tot1;
     66     e[++tot1]=(edge){x,head[y]};head[y]=tot1;
     67 }
     68 inline bool cmp(int x,int y){return a[x]<a[y];}
     69 inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
     70 inline void update(int l,int r,int &x,int y,int z)
     71 {
     72     x=++tot2;
     73     sum[x]=sum[y]+1;
     74     if(l==r)return;
     75     ls[x]=ls[y];rs[x]=rs[y];
     76     int mid=(l+r)>>1;
     77     if(z<=mid)update(l,mid,ls[x],ls[y],z);
     78     else update(mid+1,r,rs[x],rs[y],z);
     79 }
     80 inline void dfs(int x,int y)
     81 {
     82     update(1,cnt,rt[x],rt[y],c[x]);
     83     dep[x]=dep[y]+1;f[x][0]=y;
     84     for1(i,18)f[x][i]=f[f[x][i-1]][i-1];
     85     for(int i=head[x];i;i=e[i].next)
     86         if(e[i].go!=y)dfs(e[i].go,x);
     87 }
     88 inline int lca(int x,int y)
     89 {
     90     if(dep[x]<dep[y])swap(x,y);
     91     int t=dep[x]-dep[y];
     92     for0(i,18)if(t&(1<<i))x=f[x][i];
     93     if(x==y)return x;
     94     for3(i,18,0)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
     95     return f[x][0];
     96 }
     97 
     98 int main()
     99 
    100 {
    101 
    102     freopen("input.txt","r",stdin);
    103 
    104     freopen("output.txt","w",stdout);
    105 
    106     n=read();n=read();m=read();q=read();
    107     for1(i,n)a[i]=read(),b[i]=i;
    108     sort(b+1,b+n+1,cmp);
    109     for1(i,n){if(i==1||a[b[i]]!=a[b[i-1]])cnt++;d[cnt]=a[b[i]];c[b[i]]=cnt;}
    110     for1(i,m)insert(read(),read());
    111     for1(i,n)if(!dep[i])dfs(i,0);
    112     for1(i,n)fa[i]=f[i][0]?f[i][0]:i;
    113     for1(i,n)s[find(i)]++;
    114     int ans=0;
    115     while(q--)
    116     {
    117         char ch=getchar();
    118         while(ch!='Q'&&ch!='L')ch=getchar();
    119         int  x=read()^ans,y=read()^ans;
    120         if(ch=='Q')
    121         {
    122            int k=read()^ans,xx=lca(x,y),yy=f[xx][0],l=1,r=cnt;
    123            x=rt[x];y=rt[y];xx=rt[xx];yy=rt[yy];
    124            while(l!=r)
    125            {
    126               int t=sum[ls[x]]+sum[ls[y]]-sum[ls[xx]]-sum[ls[yy]],mid=(l+r)>>1;
    127               if(t>=k){x=ls[x];y=ls[y];xx=ls[xx];yy=ls[yy];r=mid;}
    128               else {x=rs[x];y=rs[y];xx=rs[xx];yy=rs[yy];l=mid+1;k-=t;}
    129            }
    130            printf("%d
    ",ans=d[l]);
    131         }
    132         else
    133         {
    134            int xx=find(x),yy=find(y);
    135            if(s[xx]>s[yy])swap(x,y),swap(xx,yy);
    136            fa[xx]=yy;s[yy]+=s[xx];
    137            insert(x,y);
    138            dfs(x,y);
    139         }
    140     }
    141 
    142     return 0;
    143 
    144 } 
    View Code

    题解:启发式合并+主席树,应该比较好想。。。

  • 相关阅读:
    性能优化随笔
    Linux文件类型及如何查看,修改文件读写权限
    ngx_pagespeed
    用U盘安装Linux系统的简单方法
    Maven 3 入门 安装与配置
    CentOS 6.2 安装教程
    各种代码文件中的注释格式
    Linux下的WebLogic安装部署
    Win8常用快捷键
    Jenkins入门总结
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4135659.html
Copyright © 2011-2022 走看看