2017 UESTC Training for Data Structures

Posted 掉血菜鸡煮熟中

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017 UESTC Training for Data Structures相关的知识,希望对你有一定的参考价值。

2017 UESTC Training for Data Structures

A    水,找区间极差,RMQ怼上去。

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 200005;

int a[N], f1[N][20], f2[N][20];
void RMQ(int n)
{
    rep(i,1,n) f1[i][0]=f2[i][0]=a[i];
    rep(j,1,19) rep(i,1,n) {
        if(i+(1<<j)-1<=n) {
            f1[i][j]=max(f1[i][j-1], f1[i+(1<<(j-1))][j-1]);
            f2[i][j]=min(f2[i][j-1], f2[i+(1<<(j-1))][j-1]);
        }
    }
}
int main()
{
    int n, q;
    scanf("%d %d", &n, &q);
        rep(i,1,n) scanf("%d", &a[i]);
        RMQ(n);
        int l, r;
        rep(i,1,q) {
            scanf("%d %d", &l, &r);
            int lg=floor(log10(r-l+1)/log10(2));
            int maxn=max(f1[l][lg], f1[r-(1<<lg)+1][lg]);
            int minn=min(f2[l][lg], f2[r-(1<<lg)+1][lg]);
            printf("%d\n", maxn-minn);
        }

    return 0;
}
View Code

C    线段树区间更新,区间求和。

题意:N个数排成一列,有三种操作。1.给一段区间内的每个数乘上一个非负整数。2.给一段区间内的每个数加上一个非负整数.3.询问一段区间的和模上P的值。

tags:由于需要区间加add和区间乘mul,需要维护两个延迟标记。对于add,修改c,则sum+=c*len(区间长度),add+c;对于mul,修改c,则sum*=c;add*=c,mul*=c。乘法分配律(add+sum)*c = add*c+sum*c;

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 100005, M = N<<2;

int n, m;
ll mod, laz1[M], laz2[M], tr[M];    //laz1[]乘的延迟标记,laz2[]加的延迟标记
void Init()
{
    rep(i,0,M-1) laz1[i]=1;
}
ll add(ll x, ll y) { return ((x%mod) + (y%mod))%mod; }
ll mul(ll x, ll y) { return ((x%mod) * (y%mod))%mod; }
void pushup(int pos)
{
    tr[pos]=add(tr[pos<<1], tr[pos<<1|1]);
}
void build(int pos, int l, int r)
{
    if(l==r) { scanf("%lld", &tr[pos]); tr[pos]%=mod; return ; }
    int mid=(l+r)>>1;
    build(pos<<1, l, mid);
    build(pos<<1|1, mid+1, r);
    pushup(pos);
}
void pushdown(int pos, int len)
{
    int lson=pos<<1, rson=pos<<1|1;
    tr[lson]= add(mul(tr[lson], laz1[pos]), (laz2[pos]*(len-(len>>1)))%mod);
    tr[rson]= add(mul(tr[rson], laz1[pos]), (laz2[pos]*(len>>1))%mod);
    laz1[lson]= mul(laz1[lson], laz1[pos]);
    laz1[rson]= mul(laz1[rson], laz1[pos]);
    laz2[lson]= add(mul(laz2[lson], laz1[pos]), laz2[pos]);
    laz2[rson]= add(mul(laz2[rson], laz1[pos]), laz2[pos]);
    laz1[pos]=1, laz2[pos]=0;
}
void update(int flag, int L, int R, int pos, int l, int r, ll c)
{
    if(L<=l && r<=R)
    {
        if(flag==1) {
            laz1[pos]=mul(laz1[pos], c);
            laz2[pos]=mul(laz2[pos], c);
            tr[pos]=mul(tr[pos], c);
        } else {
            laz2[pos]=add(laz2[pos], c);
            tr[pos]=add(tr[pos], ((r-l+1)*c)%mod);
        }
        return ;
    }
    pushdown(pos, r-l+1);
    int mid=(l+r)>>1;
    if(L<=mid) update(flag, L, R, pos<<1, l, mid, c);
    if(mid<R)  update(flag, L, R, pos<<1|1, mid+1, r, c);
    pushup(pos);
}
ll  query(int L, int R, int pos, int l, int r)
{
    if(L<=l && r<=R) return tr[pos];
    pushdown(pos, r-l+1);
    int mid=(l+r)>>1;
    ll ans=0;
    if(L<=mid) ans+=query(L, R, pos<<1, l, mid);
    if(mid<R)  ans+=query(L, R, pos<<1|1, mid+1, r);
    pushup(pos);
    return ans%mod;
}
int main()
{
    scanf("%d %lld", &n, &mod);
    Init();
    build(1, 1, n);
    scanf("%d", &m);
    int l, r, flag;   ll c;
    rep(i,1,m)
    {
        scanf("%d %d %d", &flag, &l, &r);
        if(flag!=3) {
            scanf("%lld", &c);
            update(flag, l, r, 1, 1, n, c);
        } else {
            printf("%lld\n", query(l, r, 1, 1, n));
        }
    }

    return 0;
}
View Code

D   水,树状数组

题意:n个点,每个点的rank值为x坐标不大于其x坐标,且y坐标不大于其y坐标的点的数量。(不含其自身),求出rank为0~n−1的点的数量。

tags:先对一维坐标排序,然后树状数组维护一下即可。

技术分享
// D
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define fi  first
#define se  second
typedef long long ll;
const int N = 100005;

int n;
ll  tr[N], ans[N];
pair<int,int > co[N];
void add(int x, int y) {for(; x<=n; tr[x]+=y, x+=x&-x); }
ll sum(int x) {ll ans=0; for(; x>0; ans+=tr[x], x-=x&-x); return ans; }
int main()
{
    scanf("%d", &n);
    rep(i,1,n) scanf("%d %d", &co[i].fi, &co[i].se);
    sort(co+1, co+1+n);
    rep(i,1,n)
    {
        ++ans[sum(co[i].se)];
        add(co[i].se, 1);
    }
    rep(i,0,n-1) printf("%lld\n", ans[i]);

    return 0;
}
View Code

E    水,树状数组

题意:把一个给定的1~n的排列{a1,a2,…,an}(1≤ai≤n,且ai各不相同),用最少的交换次数,变换成另一个1~n的排列{b1,b2,…,bn}。并且,每次只交换相邻的两个元素。求最小的交换次数。

tags:按b[]的顺序依次计算,直接暴力肯定超时,所以强行搞了个树状数组。。

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 100005;

int n, a[N], b[N], id[N], s[N];
ll ans;
void add(int x, int c) {for(; x; s[x]+=c, x-=x&-x); }
int sum(int x) {int ans=0; for(; x<=n; ans+=s[x], x+=x&-x); return ans; }
int main()
{
    scanf("%d", &n);
    int cnt=0;
    rep(i,1,n) {
        scanf("%d", &a[i]);
        id[a[i]]=i;
    }
    rep(i,1,n) {
        scanf("%d", &b[i]);
        int id1=id[b[i]], s1=sum(id1);
        ans+= (id1+s1-i);
        add(id1, 1);
    }
    printf("%lld\n", ans);

    return 0;
}
View Code

J    水,优先队列

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 200005;

int main()
{
    int n, ai;
    priority_queue<int , vector<int >, greater<int>  > q;
    scanf("%d", &n);
    rep(i,1,n) {
        scanf("%d", &ai);
        q.push(ai);
    }
    int ans=0;
    rep(i,1,n-1) {
        int x1=q.top(); q.pop();
        int x2=q.top(); q.pop();
        ans+= x1+x2,  q.push(x1+x2);
    }
    printf("%d\n", ans);

    return 0;
}
View Code

L    水,食物链原题

技术分享
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<bitset>
#include<vector>
#include<set>
#include<list>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 100005;

int n, k, fa[N*3];
int ans[N], ans1;
int Find(int x) {return fa[x]==x ? x : fa[x]=Find(fa[x]); }
bool same(int a, int b) {return Find(a)==Find(b); }
void Unite(int a, int b) {
    int faa=Find(a), fab=Find(b);
    if(faa!=fab) fa[faa]=fab;
}
int main()
{
    scanf("%d %d", &n, &k);
    rep(i,1,n*3) fa[i]=i;
    int d, x, y;
    bool flag=0;
    rep(ca, 1, k)
    {
        scanf("%d %d %d", &d, &x, &y);
        if(x>n || y>n) {  ans[++ans1]=ca;  continue; }
        if(d==1)
        {
            if(same(x,y+n) || same(x,y+2*n)) ans[++ans1]=ca;
            else {
                Unite(x, y); Unite(x+n, y+n); Unite(x+2*n, y+2*n);
            }
        }
        else
        {
            if(x==y || same(x,y) || same(x,y+2*n)) ans[++ans1]=ca;
            else {
                Unite(x, y+n); Unite(x+n, y+2*n); Unite(x+2*n, y);
            }
        }
    }
    rep(i,1,ans1)
        if(i==1) printf("%d", ans[i]);
        else printf(" %d", ans[i]);

    return 0;
}
View Code

M   题目意思太迷

N   老题了,带正反的并查集

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2000005;

int fa[N];
int Find(int x) {return fa[x]==x ? x : fa[x]=Find(fa[x]); }
int main()
{
    int n, m, t, a, b;
    scanf("%d %d", &n, &m);
    rep(i,1,n*2) fa[i]=i;
    rep(i,1,m) {
        scanf("%d %d %d", &t, &a, &b);
        int faa1=Find(a*2-1), faa2=Find(a*2), fab1=Find(b*2-1), fab2=Find(b*2);
        if(t==1) {
            if(faa1==fab2 || faa2==fab1) {puts("NO"); return 0; }
            fa[faa1]=fab1, fa[faa2]=fab2;
        }
        else {
            if(faa1==fab1 || faa2==fab2) {puts("NO"); return 0; }
            fa[faa1]=fab2, fa[faa2]=fab1;
        }
    }
    puts("YES");

    return 0;
}
View Code

 

以上是关于2017 UESTC Training for Data Structures的主要内容,如果未能解决你的问题,请参考以下文章

2017 UESTC Training for Data Structures

2017 UESTC Training for Dynamic Programming

2017 UESTC Training for Graph Theory

2017 UESTC Training for Dynamic Programming

2017 UESTC Training for Graph Theory

2018 UESTC Training for Search Algorithm & String