icpc/ccpc各种真题乱做

1.2017广西南宁icpc邀请赛(7/13)


http://acm.hdu.edu.cn/search.php?field=problem&key=2017ACM%2FICPC%B9%E3%CE%F7%D1%FB%C7%EB%C8%FC-%D6%D8%CF%D6%C8%FC%A3%A8%B8%D0%D0%BB%B9%E3%CE%F7%B4%F3%D1%A7%A3%A9&source=1&searchmode=source

A 暴力即可,注意爆ll

B 一共有时间,x,y,颜色四个维度,先开50棵动态开点线段树,维护颜色维度,然后线段树上按照y轴维护每个y坐标上最小的x值,最后按照时间在线回答即可

#include <bits/stdc++.h>
#define endl '\n'
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e6+10,maxm=2e7+10;
int casn,n,m,k;
int root[60];
class dsegtree{public:
#define nd node[now]
#define ndl node[node[now].son[0]]
#define ndr node[node[now].son[1]]
    struct dsegnode{
        int son[2],mn;
        void update(int x){mn=min(mn,x);}
    }node[maxm];
    int cnt;
    void init(){
        memset(root,0,sizeof root);
        node[0]={0,0,(int)1e9};
        cnt=0;
    }
    void pushup(int now){nd.mn=min(ndl.mn,ndr.mn);}
    void update(int pos,int x,int l,int r,int &now){
        if(!now) now=++cnt,nd={0,0,x};
        if(l==r) {nd.update(x);return ;}
        if(pos<=(l+r)>>1) update(pos,x,l,(l+r)>>1,nd.son[0]);
        else update(pos,x,1+((l+r)>>1),r,nd.son[1]);
        pushup(now);
    }
    int query(int s,int t,int l,int r,int now){
        if(!now) return 1e9;
        if(s<=l&&t>=r) return nd.mn;
        if(t<=(l+r)>>1) return query(s,t,l,(l+r)>>1,nd.son[0]);
        if(s>(l+r)>>1) return query(s,t,1+((l+r)>>1),r,nd.son[1]);
        return min(query(s,t,l,(l+r)>>1,nd.son[0]),query(s,t,1+((l+r)>>1),r,nd.son[1]));
    }
}tree;

int main() {
    IO;
    int a,b,c,d;
    while(cin>>a){
        if(a==3) break;
        if(a==0) tree.init();
        if(a==1||a==2){
            cin>>b>>c>>d;
            if(a==1) tree.update(c,b,1,maxn,root[d]);
            else {
                int ans=0;
                rep(i,0,50)ans+=(tree.query(c,d,1,maxn,root[i])<=b);
                cout<<ans<<endl;
            }
        }
    }
	return 0;
}

C 三元环计数,答案就是Σ(每个边被三元环包含的次数^2-每个边被三元环包含的次数)/2

#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define fi first
#define se second
#define pii pair<int,int>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=2e5+10,maxm=2e6+10;
//head
int casn,n,m,k;
vector<pii>g[maxn];
int deg[maxn],a[maxn],b[maxn],cnt[maxn],pos[maxn],v[maxn];
int main() {
    IO;
    while(cin>>n>>m){
        rep(i,1,n){
            g[i].clear();
            v[i]=deg[i]=pos[i]=0;
        }
        rep(i,1,m){
            cin>>a[i]>>b[i];
            deg[a[i]]++,deg[b[i]]++;
        }
        rep(i,1,m){
            cnt[i]=0;
            if(deg[a[i]]<deg[b[i]])g[a[i]].emplace_back(b[i],i);
            else if(deg[a[i]]>deg[b[i]])g[b[i]].emplace_back(a[i],i);
            else {
                if(a[i]<b[i]) g[a[i]].emplace_back(b[i],i);
                else g[b[i]].emplace_back(a[i],i);
            }
        }
        rep(i,1,m){
            int u=a[i],to=b[i];
            for(auto j:g[u]) pos[j.fi]=j.se,v[j.fi]=i+1;
            for(auto j:g[to]){
                int t=j.fi;
                if(v[t]==i+1){
                    cnt[i]++;
                    cnt[pos[t]]++;
                    cnt[j.se]++;
                }
            }
        }
        ll ans=0;
        rep(i,1,m) ans+=1ll*cnt[i]*(cnt[i]-1)/2;
        cout<<ans<<endl;
    }
	return 0;
}

D 递推+矩阵快速幂,记录一下完全体的矩阵板子

#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e6+10,maxm=2e6+10;
const ll mod=1e9+7;
ll n,m,casn,q,k;
class matrix{public://带取模
    int a,b;
    vector<vector<ll> > x;
    matrix(int a=1,int b=1){//行数,列数,初始均为0
        this->a=a,this->b=b;
        x.resize(a);
        for(auto &i:x){i.resize(b);std::fill(all(i),0);}
    }
    void e(int n){a=b=n;x=matrix(n,n).x;for(int i=0;i<n;i++)x[i][i]=1;}//n*n的单位矩阵
    void fill(ll xx=0){for(int i=0;i<a;i++)for(int j=0;j<b;j++)x[i][j]=xx;} //全部填为xx
    void fill(vector<vector<ll>> &y){x=y;a=y.size();b=y[0].size();}//用二维数组填充
    matrix operator *(matrix &m){
        matrix ans(a,m.b);
        for(int i=0;i<a;i++)for(int j=0;j<m.b;j++)for(int k=0;k<b;k++)if(x[i][k]&&m.x[k][j])
            ans.x[i][j]=(mod+ans.x[i][j]+(x[i][k]*m.x[k][j]+mod)%mod)%mod;
        return ans;
    }
    matrix operator +(matrix &m){
        matrix ans(a,m.b);
        for(int i=0;i<a;i++)for(int j=0;j<b;j++)ans.x[i][j]=(x[i][j]+m.x[i][j]+mod)%mod;
        return ans;
    }
    matrix operator -(matrix &m){
        matrix ans(a,m.b);
        for(int i=0;i<a;i++)for(int j=0;j<b;j++)ans.x[i][j]=(x[i][j]-m.x[i][j]+mod)%mod;
        return ans;
    }
    matrix pow(ll p){//快速幂
        matrix ans;ans.e(a);matrix t;t.fill(x);
        while(p){if(p&1) ans=t*ans;t=t*t;p>>=1;}return ans;
    }
};
const ll ff[4][4]={1,1,0,0,5,0,1,0,1,0,0,1,-1,0,0,0};
const ll fc[4]={1,5,11,36};
int main() {
    IO;
    vector<vector<ll> > f0(4,vector<ll>(4,0)),f1(1,vector<ll>(4,0));
    rep(i,0,3){
        rep(j,0,3) f0[i][j]=ff[i][j];
        f1[0][i]=fc[3-i];
    }
    while(cin>>n){
        if(n<=4) {
            cout<<fc[n-1]<<endl;
            continue;
        }
        matrix ans; ans.fill(f1);
        matrix c; c.fill(f0);
        c=c.pow(n-4);
        ans=ans*c;
        cout<<ans.x[0][0]<<endl;
    }
}

 E 前缀+后缀即可,注意边界

G 贪心,先拿走所有2个以上的部分,然后连续三个的优先级为:112 > 2XX > 111

J dfs序+01字典树,可以离线也可以持久化

离线:

#include <bits/stdc++.h>
#define endl '\n'
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e5+10,maxm=2e6+10;
//head
int casn,n,m,k;
vector<int> g[maxn];
class trie{public:
    int node[maxn*40][3],top;
    void init(){memset(node[0],0,sizeof (node[0]));top=1;}
    void add(int x,int id){
        int now,nx,rt,t;
        for(rt=0,t=31;~t;rt=nx,--t){
            nx=node[rt][now=x>>t&1];
            if(!nx) memset(node[top],0,sizeof (node[top])),node[rt][now]=nx=top++;
            node[nx][2]=id;
        }
    }
    int query(int x,int l){
        int rt,nx,now,t,ans=0;
        for(rt=0,t=31;~t;rt=nx,--t){
            now=x>>t&1,ans<<=1;
            if((nx=node[rt][!now])&&node[nx][2]<=l)ans+=1;
            else nx=node[rt][now];
        }
        return ans;
    }
}tree;
struct node{
    int id,x,l,r;
    bool operator<(node &n)const {return l>n.l;}
}ask[maxn];
int in[maxn],out[maxn],id[maxn];
int cnt,val[maxn],ans[maxn];
void dfs(int now){
    in[now]=++cnt;id[cnt]=now;
    for(auto i:g[now]) dfs(i);
    out[now]=cnt;
}
int main() {
    IO;
    while(cin>>n>>k){
        cnt=0;
        tree.init();
        rep(i,1,n) g[i].clear();
        rep(i,1,n) cin>>val[i];
        rep(i,2,n){
            int x;cin>>x;
            g[x].push_back(i);
        }
        dfs(1);
        rep(i,1,k){
            int a,b;cin>>a>>b;
            ask[i]={i,b,in[a],out[a]};
        }
        sort(ask+1,ask+1+k);
        int pos=n;
        rep(i,1,k){
            while(pos>=ask[i].l) tree.add(val[id[pos]],pos),--pos;
            ans[ask[i].id]=tree.query(ask[i].x,ask[i].r);
        }
        rep(i,1,k) cout<<ans[i]<<endl;
    }
	return 0;
}

 持久化字典树

#include <bits/stdc++.h>
#define endl '\n'
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
const int maxn=1e5+10,maxm=2e6+10;
//head
int casn,n,m,k;
int rt[maxn];
vector<int> g[maxn];
class ptrie{public:
    int node[maxn*40][2],top;
    void init(){rt[0]=node[0][1]=node[0][0]=top=0;}
    int add(int pre,int val,int bit=31){
        int now=++top;
        if(bit<0) return now;
        int t=val>>bit&1;
        node[now][t]=add(node[pre][t],val,bit-1);
        node[now][t^1]=node[pre][t^1];
        return now;
    }
    int query(int now,int pre,int val,int bit=31,int ans=0){
        if(bit<0) return ans;
        int t=val>>bit&1;
        if(node[now][t^1]-node[pre][t^1]>0) return query(node[now][t^1],node[pre][t^1],val,bit-1,ans|(1<<bit));
        return query(node[now][t],node[pre][t],val,bit-1,ans);

    }
}tree;
int in[maxn],out[maxn];
int cnt,val[maxn];
void dfs(int now){
    in[now]=++cnt;
    rt[cnt]=tree.add(rt[cnt-1],val[now]);
    for(auto i:g[now]) dfs(i);
    out[now]=cnt;
}
int main() {
    IO;
    while(cin>>n>>k){
        cnt=0;
        tree.init();
        rep(i,1,n) g[i].clear();
        rep(i,1,n) cin>>val[i];
        rep(i,2,n){
            int x;cin>>x;
            g[x].push_back(i);
        }
        dfs(1);
        rep(i,1,k){
            int a,b;cin>>a>>b;
            cout<<tree.query(rt[out[a]],rt[in[a]-1],b)<<endl;
        }
    }
	return 0;
}

 


 

2

 

转载于:https://www.cnblogs.com/nervendnig/p/10819390.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值