2017ACM/ICPC广西邀请赛-重现赛

HDU 6188 Duizi and Shunzi

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6188

思路: 

签到题,以前写的。

实现代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int MAX=1e5+10;
int main()
{
    int n,m,a[MAX],p,ans,k;
    while(scanf("%d",&n)!=EOF)
    {
        ans=0;
        for(int i = 1;i <= n;i ++)
            a[i]=0;
        for(int i = 1;i <= n;i ++)
            cin>>p,a[p]++;
        for(int i = 1;i <= n;i ++)
        {
            if(a[i]>=2)
            {
                ans+=a[i]/2;
                a[i]%=2;
            }
            if(i<=n-2&&a[i]&&a[i+1]%2&&a[i+2])
            a[i]--,a[i+1]--,a[i+2]--,ans+=1;
        }
        cout<<ans<<endl;
    }
}

HDU 6182  A Math Problem

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6182

思路: 签到

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll M = 1e18+5;
ll a[100009];
int main()
{
    ll k = 0;
    ll n,m;
    for(ll i = 1;i<=15;i++){
        ll ans = 1;
        for(ll j=1;j<=i;j++){
            ans*=i;
        }
       //cout<<ans<<endl;
       if(ans<=M)
        a[k++] = ans;
        else
            break;
    }
    while(scanf("%lld",&n)!=EOF){
            if(n>437893890380859375)
            cout<<15<<endl;
            else{
            for(ll i=0;i<k;i++){
                if(a[i]>n){
                    cout<<i<<endl;break;
                }
                else if(a[i]==n){
                    cout<<i+1<<endl;break;
                }
            }
            }
    }
    return 0;
}

HDU 6186 CS Course

链接: http://acm.hdu.edu.cn/showproblem.php?pid=6186

思路:签到题

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int M = 100050;
#define ll long long
ll a[M],or1[M],or2[M],and2[M],and1[M],xor1[M],xor2[M];
int main()
{
    ll n,q,i,x;
    while(scanf("%lld%lld",&n,&q)!=EOF){
        for(i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        or1[1] = a[1];and1[1] = a[1]; xor1[1] = a[1];
        for(i=2;i<=n;i++){
            or1[i] = (or1[i-1]|a[i]);
            and1[i] = (a[i]&and1[i-1]);
            xor1[i] = (xor1[i-1]^a[i]);
        }
        or2[n] = a[n]; and2[n] = a[n];xor2[n] = a[n];
        for(i=n-1;i>=1;i--){
            or2[i] = (a[i]|or2[i+1]);
            and2[i] = (a[i]&and2[i+1]);
            xor2[i] = (a[i]^xor2[i+1]);
        }
        //cout<<and1[2]<<" "<<(a[1]&a[2])<<endl;
        ll y;
        for(i=0;i<q;i++){
            scanf("%lld",&y);
             if(y==1)
                printf("%lld %lld %lld\n",and2[2],or2[2],xor2[2]);
            else{
                if(y==n)
                printf("%lld %lld %lld\n",and1[n-1],or1[n-1],xor1[n-1]);
                else
                printf("%lld %lld %lld\n",(and1[y-1]&and2[y+1]),(or1[y-1]|or2[y+1]),(xor1[y-1]^xor2[y+1]));
            }
        }
    }
    return 0;
}

 

HDU 6183 Color it

链接: http://acm.hdu.edu.cn/showproblem.php?pid=6183

思路:线段树+动态开点

有50种颜色,对每一种颜色建一颗线段树维护,动态开点。
第一种操作:使点(x,y)的颜色变为c
第二种:询问(1,y1),(x,y2)两点间的颜色种类数量
我们可以以y轴建线段树,横坐标为值,那么要确定两点之前是否存在某种颜色,只要询问下每个颜色在y1,y2之间最小的值(也就是横坐标).判断下最小值是否小于第二种操作给出的x,如果小于的话就代表两点间存在这种颜色。

突然发现这道题以前也写过。。。。

实现代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mid int m = (l + r) >> 1
const int M = 1e6+10;
int n = 1e6,flag=0;
int sum[M],ne=0,ls[M],rs[M],rt[100];

void update(int &k,int l,int r,int p,int num){
    if(!k){   //如果当前区间未拓展,拓展并赋值
        k = ++ne;
        sum[k] = num;
    }
    sum[k] = min(sum[k],num);//当前区间有值,更新下最小值
    if(l == r)
        return ;
    mid;
    if(p <= m) update(ls[k],l,m,p,num);
    else update(rs[k],m+1,r,p,num);
}

void query(int k,int L,int R,int l,int r,int up){
    if(!k||flag) return ;
    if(L <= l&&R >= r){
        if(sum[k]<=up)
            flag = 1;
            return;
    }
    mid;
    if(L <= m) query(ls[k],L,R,l,m,up);
    if(R > m) query(rs[k],L,R,m+1,r,up);
    return ;
}

void  init(){
   memset(rt,0,sizeof(rt));
   memset(sum,0,sizeof(sum));
   memset(ls,0,sizeof(ls));
   memset(rs,0,sizeof(rs));
   ne = 0;
}
int main()
{
    int op,x,y,z;
    while(~scanf("%d",&op)){
        if(op == 0)
            init();
        else if(op == 1){
            scanf("%d%d%d",&x,&y,&z);
            update(rt[z],1,n,y,x);
        }
        else if(op == 2){
            scanf("%d%d%d",&x,&y,&z);
            int ans = 0 ;
            for(int i = 0;i <= 50;i ++){
                 flag = 0;
                 query(rt[i],y,z,1,n,x);
                 if(flag) ans++;
            }
            printf("%d\n",ans);
        }
        else return 0;
    }
    return 0;
}

HDU 6191 Query on A Tree

链接: http://acm.hdu.edu.cn/showproblem.php?pid=6191

思路:dfs序 + 可持久化Trie树

用dfs序把树转换成序列,由于dfs序的特性,子树在序列中是连续的一段区间,那么对这段区间我们可以用可持久化trie来查询与x异或最大的值。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 1e5+10;
int a[M];
int rt[M],tot,tree[M<<5][2],son[M<<5][2],idx,in[M],out[M],cnt,head[M];
vector<int>g[M];
template <class T>
void read(T &x){
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x){
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}

void Insert(int old,int now,int x,int pos){
     if(pos < 0) return;
     int tmp = (x&(1<<pos))>0;
     tree[now][tmp] = tree[old][tmp] + 1;
     tree[now][tmp^1] = tree[old][tmp^1];
     son[now][tmp^1] = son[old][tmp^1];
     Insert(son[old][tmp],son[now][tmp]=++idx,x,pos-1);
}

void dfs(int u){
    in[u] = ++tot;
    Insert(rt[in[u]-1],rt[in[u]]=++idx,a[u],30);
    for(int i = 0;i < g[u].size();i ++){
        dfs(g[u][i]);
    }
    out[u] = tot;
}

int query(int old,int now,int x,int ans,int pos){
    if(pos < 0) return ans;
    int tmp=!!(x&(1<<pos));
    if(tree[now][tmp^1]>tree[old][tmp^1])
        return query(son[old][tmp^1],son[now][tmp^1],x,ans|(1<<pos),pos-1);
    else
        return query(son[old][tmp],son[now][tmp],x,ans,pos-1);
}
int init(){
    memset(rt,0,sizeof(rt));
    memset(son,0,sizeof(son));
    memset(tree,0,sizeof(tree));
    idx = 0,tot = 0;
}
int main(){
    int n,q,x,z,y;
    while(scanf("%d%d",&n,&q)!=EOF){
    init();
    for(int i = 1;i <= n;i ++){
        read(a[i]);
    }
    for(int i = 2;i <= n;i ++){
        read(z);
        g[z].push_back(i);
    }
    dfs(1);
    while(q--){
        read(x),read(y);
        write(query(rt[in[x]-1],rt[out[x]],y,0,30));
        putchar('\n');
    }
    for(int i = 1;i <= n;i ++)
        g[i].clear();
    }
    return 0;
}

 

posted @ 2018-08-11 13:37  冥想选手  阅读(446)  评论(0编辑  收藏  举报