2018 Multi-University Training Contest 7

1001:Age of Moyu

 在SPFA的时候开一个set或map记录一下转移到他的边的种类,转移的时候尽量选和当前这条边种类一样的边转移,玄学复杂度,记得fread读入挂和register进行常数优化。

 1 #include<bits/stdc++.h>
 2 
 3 #define maxn 100000+5
 4 #define maxm 200000+5
 5 
 6 using namespace std;
 7 
 8 struct Edge{
 9     int u,v,c,nxt;
10 }e[maxm<<1];
11 
12 unordered_map <int,int> s[maxn];
13 
14 int head[maxn],dis[maxn],inq[maxn];
15 int ind,n,m;
16 
17 void addedge(int x,int y,int c){
18     e[ind]=(Edge){x,y,c,head[x]},head[x]=ind++;
19     e[ind]=(Edge){y,x,c,head[y]},head[y]=ind++;
20 }
21 
22 void spfa(){
23     queue <int> q;
24     dis[1]=0; q.push(1); inq[1]=1;
25     s[1][0]=1;
26     while(!q.empty()){
27         int x=q.front(); q.pop(); inq[x]=0;
28         for(int i=head[x];i!=-1;i=e[i].nxt){
29             int flag=1;
30             if(s[x][e[i].c]) flag=0;
31             if(dis[e[i].v]>dis[x]+flag){
32                 dis[e[i].v]=dis[x]+flag;
33                 s[e[i].v].clear(); 
34                 if(!s[e[i].v][e[i].c]) s[e[i].v][e[i].c]=1;
35                 if(!inq[e[i].v]){
36                     inq[e[i].v]=1;                     
37                     q.push(e[i].v);
38                 }
39             }
40             else if(dis[e[i].v]==dis[x]+flag){
41                 if(!s[e[i].v][e[i].c]) {
42                     s[e[i].v][e[i].c]=1;
43                     if(!inq[e[i].v]){
44                         inq[e[i].v]=1;                     
45                         q.push(e[i].v);
46                     }
47                 }
48             }
49         }                        
50     }
51     if(dis[n]!=0x3f3f3f3f) printf("%d\n",dis[n]);
52     else puts("-1");
53 }
54 
55 namespace fastIO {
56     #define BUF_SIZE 100000
57     bool IOerror = 0;
58     inline char nc() {
59         static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
60         if(p1 == pend) {
61             p1 = buf;
62             pend = buf + fread(buf, 1, BUF_SIZE, stdin);
63             if(pend == p1) {
64                 IOerror = 1;
65                 return -1;
66             }
67         }
68         return *p1++;
69     }
70     inline bool blank(char ch) {
71         return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
72     }
73     inline int rd(int &x) {
74         char ch;
75         while(blank(ch = nc()));
76         if(IOerror) return -1;
77         for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
78         return 1;
79     }
80     #undef BUF_SIZE
81 };
82 using namespace fastIO;
83 
84 int main(){
85     freopen("x.in","r",stdin);
86     while(~rd(n)){
87         rd(m);
88         ind=0;
89         for(register int i=1;i<=n;i++) inq[i]=0,dis[i]=0x3f3f3f3f,head[i]=-1;
90         for(register int i=1;i<=m;i++){
91             int x,y,c;
92             rd(x); rd(y); rd(c);
93             addedge(x,y,c);
94         }
95         spfa();
96     }
97     return 0;
98 }
View Code

 

1002:AraBellaC

 枚举循环周期,对每个循环周期内的mxa,mnb,mxb,mnc二分寻找,要保证(mxa-1)%len<(mnb-1)%len和(mxb-1)%len<(mnc-1)%len。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
using namespace std;

const int MAX=1e5+5;
int t,m;
int a,b,c;
vector<int> E[3];

void update(int aa,int bb,int cc){
    int flag=0;
    if(aa<a) flag=1;
    else if(aa==a&&bb<b) flag=1;
    else if(aa==a&&bb==b&&cc<c) flag=1;
    if(flag) a=aa,b=bb,c=cc;
}

int main(){
    int i,j;
    
    //freopen("data.in","r",stdin);
    scanf("%d",&t);
    while(t--){
        int mx=0;
        a=b=c=0x3f3f3f3f;
        for(i=0;i<3;i++) E[i].clear(),E[i].push_back(0);
        scanf("%d",&m);
        for(i=0;i<m;i++){
            int pos;char c;
            scanf("%d %c",&pos,&c);
            E[c-'A'].push_back(pos);
            mx=max(mx,pos);
        }
        for(i=0;i<3;i++) E[i].push_back(MAX),sort(E[i].begin(),E[i].end());
        for(i=1;i<=mx;i++){
            int mxa=0,mnc=MAX,mxb=0,mnb=MAX;
            for(j=(mx+i-1)/i;j>0;j--){
                int tmp=*(upper_bound(E[0].begin(),E[0].end(),j*i)-1);
                if(tmp>(j-1)*i) mxa=max(mxa,(tmp-1)%i);
                tmp=*upper_bound(E[1].begin(),E[1].end(),(j-1)*i);
                if(tmp<=j*i) mnb=min(mnb,(tmp-1)%i);
                tmp=*(upper_bound(E[1].begin(),E[1].end(),j*i)-1);
                if(tmp>(j-1)*i) mxb=max(mxb,(tmp-1)%i);
                tmp=*upper_bound(E[2].begin(),E[2].end(),(j-1)*i);
                if(tmp<=j*i) mnc=min(mnc,(tmp-1)%i);
                if(mxa>=mnb||mxb>=mnc) break;
            }
            if(j==0) update(mxa+1,mxb-mxa,i-mxb-1);
        }
        if(a==0x3f3f3f3f) puts("NO");
        else printf("%d %d %d\n",a,b,c);
    }
    
    return 0;
} 
View Code

 

1005:GuGuFishtion

首先推公式,欧拉函数是积性函数但不是一个完全积性函数,所以a,b不互质的情况下肯定还有一个偏移量。然后质因数分解一下a,b可以用数论知识证明差一个GCD(a,b)/Φ(GCD(a,b)),所以对于所有a,b不互质的情况下对答案的贡献是GCD(a,b)/Φ(GCD(a,b)),互质的话贡献是1。然后容斥,枚举k,容斥计算以k作为gcd的数对有多少个,然后乘上贡献就行了。

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N=1000000+5;

LL tmp,ans;
long long n,m,p;
long long phi[N], cnt, prime[N/3],dy[N], val[N], q[N],sum_val[N],sum[N],inv[N],mu[N];
bool com[N];

int primes;
void get_prime_phi(){
   memset( com, false, sizeof( com ) );
    primes = 0;
    phi[1] = 1;
    mu[1] = 1;
    for (int i = 2; i < N; ++i){
        if (!com[i]) {
            prime[primes++] = i;
            phi[i] = i-1;
            mu[i] = -1;
        }
        for (int j = 0; j < primes && i*prime[j] <= N; ++j){
            com[i*prime[j]] = true;
            if (i % prime[j]){
                phi[i*prime[j]] = phi[i]*(prime[j]-1);
                mu[i*prime[j]] = -mu[i];
            }
            else {
                mu[i*prime[j]] = 0;
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
        }
    }
}

int lim;
long long f[N],F[N];

void get(){
    for(int i=1;i<=lim;++i)   F[i]=1ll*(m/i)*(n/i)%p;
    for(int i=lim;i>0;--i){
            f[i]=F[i];
        for(int j=i+i;j<=lim;j+=i)
            f[i]-=1ll*f[j]%p;
    }
    for(int i=1;i<=lim;++i)   f[i]%=p;
}


int main(){
    //freopen("case.in","r",stdin);
    int T;
    scanf("%d",&T);
    get_prime_phi();

    while(T--){
        scanf("%lld%lld%lld",&n,&m,&p); tmp=ans=0;
        lim=min(n,m);
        memset(inv,0,sizeof(inv));
        memset(f,0,sizeof(f));
        inv[1]=1;
        for(register int i=2;i<=lim+2;i++)
            inv[i]=(LL)(p-p/i)*inv[p%i]%p;
        get();

        for(register int i=1;i<=lim;i++){
            val[i]=(LL)i*inv[phi[i]]%p;
            ans=(ans+(LL)val[i]*f[i]%p)%p;
            if(ans<0) ans+=p;
            //cout<<ans<<endl;
        }

        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

1006:Lord Li's problem

有意思的dp;
根据异或的性质,X_0⊕X_1⊕X_2⊕X_3⊕…..⊕X_(M-1)=S⊕T 
计算出S⊕T中一共有cnt个1,将这个二进制数标准化,使它成为前面N-cnt个0,后cnt个1的二进制数,答案保持不变,问题变为:用K个N位且有3个1的不同二进制数进行异或,最终得到前面N-cnt个0,后面cnt个1这个二进制数,有多少种方案? 
递推。设d[K][M]表示用K个N位且有3个1的不同二进制数进行异或,最终得到前面N-cnt个0,后面cnt个1这个二进制数的方案数。
然后可以容易推出状态只可以从上一层的-1,-3,+1,+3这些状态转移过来 考虑加入重复串的影响,d[i][j]-= (d[i-2][j] * (C[n][3]-i+2);表示去除加入i-2个数字并且后面有j个1这个二进制数但后来又异或上两个之前没用过的相同的数的方案数, 考虑二进制数加入的先后顺序给答案带来的额外贡献,d[i][j]=d[i][j]*inv[i]%mod
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
const long long mod=19260817;

long long dp[30][50],c[50][50],inv[110];
char S[45],T[45];
int n,k;

void init()
{
    memset(dp,0,sizeof(dp));
}

int main()
{
    int i,j;
    c[0][0]=1;
    for(i=1;i<=45;i++)
    {
        c[i][0]=c[i][i]=1;
        for(j=1;j<i;j++)
        {
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        }
    }

    inv[1]=1;
    for(i=2;i<=60;i++)
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;

    int cas=1;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(n==0&&k==0) break;
        init();
        scanf("%s%s",S,T);
        int num_1=0;
        for(i=0;i<n;i++)
            if((S[i]-'0')^(T[i]-'0')==1) num_1++;
        dp[0][0]=1;
        for(i=1;i<=k;i++)
        {
            for(j=0;j<=n;j++)
            {
                if(j>=3) dp[i][j]=(dp[i][j]+dp[i-1][j-3]*c[j][3])%mod;
                if(j>=1) dp[i][j]=(dp[i][j]+dp[i-1][j-1]*c[j][2]%mod*c[n-j][1])%mod;
                if(j+3<=n) dp[i][j]=(dp[i][j]+dp[i-1][j+3]*c[n-j][3])%mod;
                if(j+1<=n) dp[i][j]=(dp[i][j] + dp[i - 1][j + 1] * c[j][1] %mod* c[n - j][2]) % mod;
                if (i - 2 >= 0)dp[i][j] = (dp[i][j] - (dp[i - 2][j] * (c[n][3] - i + 2))) % mod;
                dp[i][j] = dp[i][j] * inv[i] % mod;
                if(dp[i][j]<0) dp[i][j]+=mod;
            }
        }
        printf("Case #%d: %lld\n",cas++, dp[k][num_1]);
    }
    return 0;
}
View Code

1007:Reverse Game

 线段树上维护并查集,用线段树维护[L,R]之间所有列的联通块(并查集)同时存下列L和R的黑白情况,然后每次修改暴力更新并查集。处理首尾成环的情况就考虑线段树根节点的L,R列并查集是否联通。

小TIPS:这题有大量并查集的fa数组初始化,如果暴力初始化会T,可以学标程将更改过的节点打好标记,初始化的时候只初始化标记了的节点。

#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;

#define Js(j,l) (j-1)*n+l;

int n,m;
int a[205][205];
int fa[40005];
int List[40005],tot;
bool used[40005];

struct Tree
{
    int l,r;
    int d[2][205];
    int sign[2][205];
    int numb;
    int numw;
}tree[1000];

namespace fastIO {
    #define BUF_SIZE 100000
    bool IOerror = 0;
    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if(p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if(pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch) {
        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
    }
    inline int rd(int &x) {
        char ch;
        while(blank(ch = nc()));
        if(IOerror) return -1;
        for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
        return 1;
    }
    #undef BUF_SIZE
};

int Find(int k)
{
    if (fa[k]==k) return k;
    else
    {
        if (used[k]==0)
        {
            used[k]=1;
            tot++;
            List[tot]=k;
        }
        return fa[k]=Find(fa[k]);
    }
}

void pushup(int i)
{
    int numb=tree[i*2].numb+tree[i*2+1].numb;
    int numw=tree[i*2].numw+tree[i*2+1].numw;

    for (int j=1;j<=n;j++)
        if (tree[i*2].d[1][j]==tree[i*2+1].d[0][j])
        {
            int a,b;
            a=Find(tree[i*2].sign[1][j]);
            b=Find(tree[i*2+1].sign[0][j]);
            if (a==b) continue;
            fa[a]=b;
            if (used[a]==0)
                {
                used[a]=1;
                tot++;
                List[tot]=a;
                }
            if (tree[i*2].d[1][j]==0) numw--;
            else numb--;
        }
    tree[i].numw=numw;
    tree[i].numb=numb;
    for (int j=1;j<=n;j++)
    {
        tree[i].d[0][j]=tree[i*2].d[0][j];
        tree[i].d[1][j]=tree[i*2+1].d[1][j];

        tree[i].sign[0][j]=Find(tree[i*2].sign[0][j]);
        tree[i].sign[1][j]=Find(tree[i*2+1].sign[1][j]);
    }
}

void Init(int i,int l)
{
    tree[i].numw=tree[i].numb=0;
    for (int j=1;j<=n;j++)
        tree[i].d[0][j]=tree[i].d[1][j]=a[j][l];
    for (int j=1;j<=n;j++)
        if (a[j][l]!=a[j-1][l] || j==1)
        {
            tree[i].sign[0][j]=tree[i].sign[1][j]=Js(j,l);
            if (a[j][l]==0) tree[i].numw++;
            else tree[i].numb++;
        }
        else tree[i].sign[0][j]=tree[i].sign[1][j]=tree[i].sign[0][j-1];
}

void build(int i,int l,int r)
{
    tree[i].l=l;
    tree[i].r=r;
    if (l==r)
    {
        Init(i,l);
        return ;
    }
    int mid=(tree[i].l+tree[i].r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    pushup(i);
}

void Change(int i,int y)
{
    if (tree[i].l==tree[i].r && tree[i].l==y)
    {
        Init(i,y);
        return ;
    }
    int mid=(tree[i].l+tree[i].r)/2;
    if (y<=mid) Change(i*2,y);
    else Change(i*2+1,y);
    pushup(i);
}

int main()
{
    int t;
    //scanf ("%d",&t);
    fastIO::rd(t);
    while (t--)
    {
        memset(tree,0,sizeof(tree));
        memset(List,0,sizeof(List));
        //splay(n);
        fastIO::rd(n);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                //splay(a[i][j]);
                fastIO::rd(a[i][j]);
        for (int i=1;i<=n*n;i++)
            fa[i]=i;
        build(1,1,n);
        for (int i=1;i<=n*n;i++)
            fa[i]=i;
        //scanf ("%d",&m);
        fastIO::rd(m);
        tot=0;

        memset(used,0,sizeof(used));
        while (m--)
        {
            int x,y,o;
            //scanf ("%d",&o);
            fastIO::rd(o);
            if (o==1)
            {
                //scanf ("%d",&y);
                fastIO::rd(y);
                for (int i=1;i<=n;i++)
                    a[i][y]=1^a[i][y];
            }
            else
            {
                //scanf ("%d %d",&x,&y);
                fastIO::rd(x);
                fastIO::rd(y);
                a[x][y]=a[x][y]^1;
            }
            Change(1,y);

            int numb=tree[1].numb;
            int numw=tree[1].numw;

            for (int j=1;j<=n;j++)
                if (tree[1].d[1][j]==tree[1].d[0][j])
                {
                    int a,b;
                    a=Find(tree[1].sign[1][j]);
                    b=Find(tree[1].sign[0][j]);
                    if (a==b) continue;
                    fa[a]=b;
                    if (used[a]==0)
                    {
                        used[a]=1;
                        tot++;
                        List[tot]=a;
                    }
                    if (tree[1].d[1][j]==0) numw--;
                    else numb--;
                }

            printf ("%d %d\n",numw,numb);
            for (int i=1;i<=tot;i++)
                fa[List[i]]=List[i];
            for (int i=1;i<=tot;i++)
                used[List[i]]=0;
            tot=0;
        }
    }
    return 0;
}
View Code

 

1008:Traffic Network in Numazu

 将环上的一个节点定为根节点,根节点连在的环上的一条边切开,得到一颗树,将树的权值按dfs序排列,用树状数组动态维护。若查询节点的lca不经过环,则直接为树上的距离,若经过环,可在两点在树上的距离以及绕环走的距离中取一个最小值作为答案,这些都可通过与LCA相关的计算得出,细节处理见代码。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 
  6 #define maxn 100000+5
  7 
  8 using namespace std;
  9 
 10 struct Edge{
 11     int u,v,c,nxt;
 12 }e[maxn<<1];
 13 
 14 int dfn[maxn<<1]; long long bit[maxn<<1];
 15 int data[maxn][3],fa[maxn][20],st[maxn],ed[maxn],head[maxn],flag[maxn],tag[maxn],du[maxn],dep[maxn];
 16 int n,q,ind,root,cut,leaf,pos;
 17 
 18 void addedge(int x,int y,int z){
 19     e[ind]=(Edge){x,y,z,head[x]},head[x]=ind++;
 20     e[ind]=(Edge){y,x,z,head[y]},head[y]=ind++;
 21 }
 22 
 23 int findroot(int x,int p){
 24     tag[x]++;
 25     if(tag[x]==2){
 26         root=x; leaf=p; flag[x]=1;
 27         return 1;
 28     }
 29     for(int i=head[x];i!=-1;i=e[i].nxt)
 30         if(e[i].v!=p){
 31             int tmp=findroot(e[i].v,x);
 32             if(tmp==1){
 33                 cut=i; flag[x]=1;
 34                 return 2;
 35             }
 36             else if(tmp==2){
 37                 flag[x]=1;
 38                 if(tag[x]==2) return 3;
 39                 return 2;
 40             }
 41             else if(tmp==3) return 3;
 42         }
 43     return 0;
 44 }
 45 
 46 void dfs(int x,int p){
 47     for(int i=head[x];i!=-1;i=e[i].nxt)
 48         if(e[i].v!=p && i!=cut && i!=(cut^1)){
 49             fa[e[i].v][0]=x; dep[e[i].v]=dep[x]+1;
 50             dfn[++pos]=e[i].c; st[e[i].v]=pos;
 51             dfs(e[i].v,x);
 52             dfn[++pos]=-e[i].c; ed[e[i].v]=pos;
 53         }    
 54 }
 55 
 56 void add(int x,int val){
 57     int N=maxn<<1;
 58     while(x<N){
 59         bit[x]+=val;
 60         x+=x&-x;
 61     }
 62 }
 63 
 64 long long sum(int x){
 65     long long res=0;
 66     while(x){
 67         res+=bit[x];
 68         x-=x&-x;        
 69     }
 70     return res;
 71 }
 72 
 73 void init(){
 74     for(int i=1;i<20;i++)
 75         for(int j=1;j<=n;j++)
 76             fa[j][i]=fa[fa[j][i-1]][i-1];    
 77     for(int i=1;i<=pos;i++)
 78         add(i,dfn[i]);
 79      
 80 }
 81 
 82 int getlca(int x,int y){
 83 
 84     if(dep[x]>dep[y]) swap(x,y);
 85     for(int i=19;i>=0;i--) if((dep[y]-dep[x])&(1<<i)) y=fa[y][i];
 86     if(x==y) return x;
 87     for(int i=19;i>=0;i--)
 88         if(fa[x][i]!=fa[y][i]){
 89             x=fa[x][i];
 90             y=fa[y][i];
 91         }
 92     return fa[x][0];
 93 }
 94 
 95 int main(){
 96 #ifndef ONLINE_JUDGE
 97     freopen("x.in","r",stdin);
 98     freopen("x.out","w",stdout);
 99 #endif
100     int T;
101     scanf("%d",&T);
102     while(T--){
103         scanf("%d%d",&n,&q); pos=ind=0;
104         for(int i=1;i<=n;i++){
105             head[i]=-1;
106             tag[i]=du[i]=bit[i]=bit[i+n]=flag[i]=0;            
107             for(int j=0;j<20;j++) fa[i][j]=0;
108         }
109         for(int i=1;i<=n;i++){
110             int x,y,c;
111             scanf("%d%d%d",&x,&y,&c);
112             addedge(x,y,c); du[x]++; du[y]++;
113             data[i][0]=x; data[i][1]=y; data[i][2]=c;
114         }
115         bool fg=false;
116         for(int i=1;i<=n;i++)
117             if(du[i]==1){ fg=true; findroot(i,0); break; }
118         if(!fg) findroot(1,0);
119         dep[root]=1; st[root]=0;
120         dfs(root,0);
121         init();
122         for(int i=1;i<=q;i++){
123             int op,x,y;
124             scanf("%d%d%d",&op,&x,&y);
125             if(op==0){                
126                 if(cut/2+1==x){ data[x][2]=y; continue; }                
127                 int a=data[x][0],b=data[x][1];
128                 if(dep[a]<dep[b]) swap(a,b);
129                 add(st[a],-data[x][2]); add(ed[a],data[x][2]);
130                 data[x][2]=y;
131                 add(st[a],data[x][2]); add(ed[a],-data[x][2]);
132             }
133             else{
134                 int p=getlca(x,y);
135                 long long ans=sum(st[x])+sum(st[y])-sum(st[p])*2;
136                 if(flag[p]){
137                     int px=getlca(x,leaf),py=getlca(y,leaf);
138                     if(dep[px]<dep[py]) swap(x,y),swap(px,py);
139                     long long tmp=sum(st[x])+sum(st[leaf])-sum(st[px])*2+sum(st[y])+data[cut/2+1][2];
140                     printf("%lld\n",min(tmp,ans));
141                 }
142                 else printf("%lld\n",ans);                
143             }
144         }
145     }
146     return 0;
147 }
View Code

 

1009:Tree

 将每个点向上跳能到达的节点标记为一个新的父节点,根据这个新的父节点能建出一颗新树,根节点表示为能跳到原树的外部,故答案即为某个点的深度。为了动态维护这颗树,可以考虑使用LCT维护,通知记录子树的大小,Access后子树大小即为所求点的深度。

  1 #include<bits/stdc++.h>
  2 
  3 #define maxn 100000+5
  4 
  5 using namespace std;
  6 
  7 struct Edge{
  8     int u,v,nxt;
  9 }e[maxn<<1];
 10 
 11 struct Splay_Tree{
 12     int ch[2];
 13     int sz,flip,fa,pf;
 14     void init(){
 15         ch[0]=ch[1]=sz=flip=fa=pf=0;
 16     }
 17 }tr[maxn<<1];
 18 
 19 int st[maxn],head[maxn],mf[maxn],dep[maxn],fa[maxn][20];
 20 int n,q,top,ind;
 21 
 22 inline int in(){
 23     int x=0; char ch=getchar();
 24     for(;!isdigit(ch);ch=getchar());
 25     for(; isdigit(ch);ch=getchar()) x=x*10+ch-'0';
 26     return x;
 27 }
 28 
 29 inline void Pushdown(int k){
 30     if(tr[k].flip){
 31         tr[k].flip^=1;
 32         tr[tr[k].ch[0]].flip^=1;
 33         tr[tr[k].ch[1]].flip^=1;
 34         swap(tr[k].ch[0],tr[k].ch[1]);
 35     }
 36 }
 37 
 38 inline void Update(int k){
 39     tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz+1;
 40 }
 41 
 42 void Rotate(int &k,int d){
 43     int t=tr[k].ch[d^1],Fa=tr[k].fa,Pf=tr[k].pf; 
 44     tr[k].pf=0; tr[k].fa=t;    tr[tr[t].ch[d]].fa=k;
 45     tr[t].pf=Pf; tr[t].fa=Fa;
 46     tr[k].ch[d^1]=tr[t].ch[d]; tr[t].ch[d]=k;
 47     Update(k); Update(t); k=t;
 48 }
 49 
 50 void Splay(int &k,int x){
 51     int d1=(tr[tr[k].ch[0]].sz<x?1:0),t=tr[k].ch[d1];
 52     if(d1==1) x-=tr[tr[k].ch[0]].sz+1;
 53     if(x){
 54         int d2=(tr[tr[t].ch[0]].sz<x?1:0);
 55         if(d2==1) x-=tr[tr[t].ch[0]].sz+1;
 56         if(x){
 57             Splay(tr[t].ch[d2],x);
 58             if(d1==d2) Rotate(k,d1^1);
 59             else Rotate(tr[k].ch[d1],d1);    
 60         }
 61         Rotate(k,d1^1);
 62     }
 63 }
 64 
 65 int rankk(int k,int &rt){
 66     int res=tr[tr[k].ch[0]].sz+1;
 67     st[++top]=k; rt=k;
 68     while(tr[k].fa){
 69         int p=tr[k].fa;
 70         st[++top]=p;
 71         if(tr[p].ch[0]!=k)
 72             res+=tr[tr[p].ch[0]].sz+1;
 73         k=p;
 74     }
 75     rt=k;
 76     return res;
 77 }
 78 
 79 inline void Haha(int k){
 80     int rt,x=rankk(k,rt);
 81     while(top) Pushdown(st[top--]);
 82     Splay(rt,x);
 83 }
 84 
 85 inline void Cutright(int k){
 86     if(tr[k].ch[1]){
 87         tr[tr[k].ch[1]].pf=k; 
 88         tr[tr[k].ch[1]].fa=0;
 89         tr[k].ch[1]=0;
 90     }
 91 }
 92 
 93 void Access(int k){
 94     Haha(k); Cutright(k);
 95     while(tr[k].pf){
 96         int u=tr[k].pf;
 97         Haha(u); Cutright(u);
 98         tr[u].ch[1]=k;
 99         tr[k].pf=0; tr[k].fa=u;
100         Update(u); k=u;    
101     }
102 }
103 
104 inline void Beroot(int k){
105     Access(k); Haha(k);
106     tr[k].flip^=1;
107 }
108 
109 inline void Cut(int k){
110     Access(k); Haha(k);
111     int l=tr[k].ch[0];
112     tr[k].ch[0]=0;
113     if(l){
114         tr[l].fa=0;
115         tr[l].pf=0;
116         Update(k);
117         Haha(l);
118     }
119 }
120 
121 inline void Link(int k,int p){
122     Access(k); Beroot(p);
123     tr[p].pf=k;
124 }
125 
126 void dfs(int x,int fa){
127     for(int i=head[x];i!=-1;i=e[i].nxt)
128         if(e[i].v!=fa){
129             dep[e[i].v]=dep[x]+1;
130             dfs(e[i].v,x);
131         }
132     
133 }
134 
135 void init(){
136     for(int i=1;i<20;i++)
137         for(int j=1;j<=n;j++)
138             fa[j][i]=fa[fa[j][i-1]][i-1];
139 }
140 
141 int da(int x,int k){
142     for(int i=19;i>=0;i--) if(k&(1<<i)) x=fa[x][i];
143     return x;
144 }
145 
146 void addedge(int x,int y){
147     e[ind]=(Edge){x,y,head[x]},head[x]=ind++;
148 }
149 
150 int main(){
151     int T;
152     T=in();
153     while(T--){        
154         n=in(); 
155         memset(fa,0,sizeof(fa)); 
156         for(int i=1;i<=n+1;i++) tr[i].init();
157         ind=top=0;
158         tr[1].sz=tr[n+1].sz=1; tr[1].pf=n+1;
159         for(int i=1;i<=n;i++) head[i]=-1;
160         for(int i=2;i<=n;i++){
161             int x=in(); fa[i][0]=x;
162             addedge(x,i); tr[i].sz=1; 
163         }
164         for(int i=1;i<=n;i++) mf[i]=in();
165         dfs(1,0); init();        
166         for(int i=1;i<=n;i++){
167             if(mf[i]>dep[i]){
168                 tr[i].pf=n+1;
169                 continue;
170             }
171             int p=da(i,mf[i]);
172             tr[i].pf=p;
173         }
174         q=in();
175         for(int i=1;i<=q;i++){
176             int op,x,y,newa;
177             op=in(); x=in();
178             if(op==1){
179                 Beroot(n+1);
180                 Access(x); Haha(x);
181                 printf("%d\n",tr[tr[x].ch[0]].sz);
182             }
183             else{
184                 newa=in(); Cut(x); 
185                 if(newa>dep[x]) Link(n+1,x);            
186                 else{
187                     y=da(x,newa);
188                     Link(y,x);
189                 }
190             }
191         }
192     }
193     return 0;
194 }
View Code

 

1010:Sequence

矩阵快速幂,首先可以看出这题只能用矩阵快速幂,然后考虑对p进行分块,处理出p/i这个矩阵的指数,然后就矩阵快速幂了

 

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
using namespace std;

const int MAX=5; 
const int mod=1e9+7;

struct Matrix{
    long long mp[MAX][MAX];  //矩阵 
    int n,m;  //行 列 
    
    Matrix(int _n,int _m){
        n=_n,m=_m;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                mp[i][j]=0;
    }
    
    Matrix operator+(const Matrix &b)const{
        Matrix tmp(n,m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                tmp.mp[i][j]=mp[i][j]+b.mp[i][j];
                tmp.mp[i][j]%=mod;
            }
        return tmp;
    }
    
    Matrix operator*(const Matrix &b)const{
        Matrix ret(n,b.m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                for(int k=0;k<m;k++){
                    ret.mp[i][j]+=mp[i][k]*b.mp[k][j];
                    ret.mp[i][j]%=mod;
                }
        return ret;
    }
    
    Matrix operator^(long long k)const{
        Matrix ret(n,m),b(n,m);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++)
                b.mp[i][j]=mp[i][j];
            ret.mp[i][i]=1;
        }
        while(k){
            if(k&1)
                ret=ret*b;
            b=b*b;
            k>>=1;
        }
        return ret;
    }
};

int t;
int a,b,c,d,p,n;

int main(){
    int i;
    
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&p,&n);
        if(n==1) printf("%d\n",a);
        else if(n==2) printf("%d\n",b);
        else{
            Matrix mc(3,1);
            mc.mp[0][0]=b;
            mc.mp[1][0]=a;
            mc.mp[2][0]=1;
            int now=3;
            Matrix mb(3,3);
            mb.mp[0][0]=d,mb.mp[0][1]=c,mb.mp[1][0]=1,mb.mp[2][2]=1;
            while(now<=n){
                int tmp=p/now;
                mb.mp[0][2]=tmp;
                if(tmp==0){
                    mc=(mb^(n-now+1))*mc;
                    break;
                }
                int x=p/tmp;
                if(x>n) x=n;
                mc=(mb^(x-now+1))*mc;
                now=x+1;
            } 
            printf("%lld\n",mc.mp[0][0]);
        }
    }
    
    return 0;
} 
View Code

 

1011:Swordsman

 瞎贪就行,按每个关键字开优先队列,直到从最后一个队列弹出表示可以击杀,同时加上exp就好。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
#include <stack>
#include <set>
#include <map>
using namespace std;

struct FastIO
{
    static const int S = 200;
    int wpos;
    char wbuf[S];
    FastIO() :wpos(0) {}
    inline int xchar()
    {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len) pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int read()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
}io;

const int MAX=1e5+5; 

int t,n,k,ans;
struct node{
    int x[10],y[10];
}mon[MAX];
int v[10];

struct cmpa{
    bool operator()(node a,node b){
        return a.x[0]>b.x[0];
    }
};
struct cmpb{
    bool operator()(node a,node b){
        return a.x[1]>b.x[1];
    }
};
struct cmpc{
    bool operator()(node a,node b){
        return a.x[2]>b.x[2];
    }
};
struct cmpd{
    bool operator()(node a,node b){
        return a.x[3]>b.x[3];
    }
};
struct cmpe{
    bool operator()(node a,node b){
        return a.x[4]>b.x[4];
    }
};

priority_queue<node,vector<node>,cmpa> a;
priority_queue<node,vector<node>,cmpb> b;
priority_queue<node,vector<node>,cmpc> c;
priority_queue<node,vector<node>,cmpd> d;
priority_queue<node,vector<node>,cmpe> e;

int main(){
    int i,j;
    
    //freopen("1.in","r",stdin);
    //freopen("10.out","w",stdout);
    t=io.read();
    while(t--){
        ans=0;
        while(!a.empty()) a.pop();
        while(!b.empty()) b.pop();
        while(!c.empty()) c.pop();
        while(!d.empty()) d.pop();
        while(!e.empty()) e.pop();
        n=io.read(),k=io.read();
        for(i=0;i<k;i++) v[i]=io.read();
        for(i=0;i<n;i++){
            for(j=0;j<k;j++) mon[i].x[j]=io.read();
            for(j=0;j<k;j++) mon[i].y[j]=io.read();
            a.push(mon[i]);
        }
        if(k==1){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    ans++;
                    a.pop();
                    v[0]+=now.y[0];
                }
                else break;
            }
        }
        else if(k==2){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            ans++;
                            b.pop();
                            v[0]+=now.y[0];
                            v[1]+=now.y[1];
                        }
                        else break;
                    }
                }
                else break;
            }
        }
        else if(k==3){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            b.pop();
                            c.push(now);
                            while(!c.empty()){
                                node now=c.top();
                                if(v[2]>=now.x[2]){
                                    ans++;
                                    c.pop();
                                    v[0]+=now.y[0];
                                    v[1]+=now.y[1];
                                    v[2]+=now.y[2];
                                }
                                else break;
                            }
                        }
                        else break;
                    }
                }
                else break;
            }
        }
        else if(k==4){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            b.pop();
                            c.push(now);
                            while(!c.empty()){
                                node now=c.top();
                                if(v[2]>=now.x[2]){
                                    c.pop();
                                    d.push(now);
                                    while(!d.empty()){
                                        node now=d.top();
                                        if(v[3]>=now.x[3]){
                                            ans++;
                                            d.pop();
                                            v[0]+=now.y[0];
                                            v[1]+=now.y[1];
                                            v[2]+=now.y[2];
                                            v[3]+=now.y[3];
                                        }
                                        else break;
                                    }
                                }
                                else break;
                            }
                        }
                        else break;
                    }
                }
                else break;
            }
        }
        else if(k==5){
            while(!a.empty()){
                node now=a.top();
                if(v[0]>=now.x[0]){
                    a.pop();
                    b.push(now);
                    while(!b.empty()){
                        node now=b.top();
                        if(v[1]>=now.x[1]){
                            b.pop();
                            c.push(now);
                            while(!c.empty()){
                                node now=c.top();
                                if(v[2]>=now.x[2]){
                                    c.pop();
                                    d.push(now);
                                    while(!d.empty()){
                                        node now=d.top();
                                        if(v[3]>=now.x[3]){
                                            d.pop();
                                            e.push(now);
                                            while(!e.empty()){
                                                node now=e.top();
                                                if(v[4]>=now.x[4]){
                                                    ans++;
                                                    e.pop();
                                                    v[0]+=now.y[0];
                                                    v[1]+=now.y[1];
                                                    v[2]+=now.y[2];
                                                    v[3]+=now.y[3];
                                                    v[4]+=now.y[4];
                                                }
                                                else break;
                                            }
                                        }
                                        else break;
                                    }
                                }
                                else break;
                            }
                        }
                        else break;
                    }
                }
                else break;
            }
        }
        
        printf("%d\n",ans);
        for(i=0;i<k;i++) printf("%d%c",v[i],i==k-1?'\n':' ');
    }
    
    return 0;
} 
View Code

 

posted @ 2018-08-14 19:53  Hetui  阅读(324)  评论(0编辑  收藏  举报