1. 程式人生 > >10-20

10-20

std ems 一個人 ace bfs tor start else tchar

比較水的題目吧

T1:給一個序列,序列中有四種操作,問有多少個非空子序列令一個機器人經過變換後再回到原位

數據量很小,n^2拿80,另外20只有左右兩種命令,求一個類似於前綴和的東西,如果sumi==sumj證明有一種

#include<bits/stdc++.h>
using namespace std;

struct hehe{
    int x,y;
};
int n,cnt[800100];
char s[400100];

void work1(){
    hehe a;
    int ans=0;
    for(int i=1;i<=n;++i){
        a.x=0; a.y=0
; for(int j=i;j<=n;++j){ if(s[j-1]==U) a.y++; else if(s[j-1]==D) a.y--; else if(s[j-1]==L) a.x--; else if(s[j-1]==R) a.x++; if(!a.x && !a.y) ans++; } } cout<<ans<<endl; } void work2(){
int x=0,ans=0; for(int i=1;i<=n;++i){ int xx=x; if(xx<0) xx=n-xx; ans+=cnt[xx]; cnt[xx]++; if(s[i-1]==L) x++; else if(s[i-1]==R) x--; } cout<<ans<<endl; } int main(){ freopen("command.in","r",stdin); freopen("command.out
","w",stdout); cin>>n; scanf("%s",s); if(n<=4000) work1(); else work2(); fclose(stdin);fclose(stdout); return 0; }

T2:將n種顏色塗到n種卡片上,每種卡片有兩張,將兩張卡片一個正面朝上,一個反面朝上,打亂後將一個正面朝上的和一個反面朝上的放到一張桌子上(總共n張桌子),一個人會用1s的時間打開一個桌子上的反過來的卡片,並且走到另一個正面是這個顏色的桌子,對於Q次詢問,求每次ki秒後這個人在哪站著。

對於30%的數據來說模擬即可,對於100%的數據來說,考慮到一定會出現循環的情況,做一個類似於連通分量的東西,求出每一個塊的循環節y,那麽問題就是每次詢問的ki%y後的數怎麽處理了。我的做法是開了一個結構體,存了每個桌子屬於第幾個塊,在這個塊中他是第幾個,這樣排序後就能O(1)的時間解決ki%y後的問題了

#include<bits/stdc++.h>
using namespace std;

struct hehe{
    int x,y,dfn;
}a[100100];
struct hh{
    int op,id,s,dfn;
}a1[100100];
struct haha{
    int id,y;
}e[100100];
int n,m,cnt=0,op[100100],kuai[100100],num=0,start[100100];

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==-) f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch-0); ch=getchar();}
    return x*f;
}

inline void put(int x){
    char ch[30];
    int t=0;
    if(x<0){
        putchar(-);
        x=-x;
    }
    else if(x==0) putchar(0);
    while(x){
        ch[++t]=x%10+0;
        x/=10;
    }
    while(t) putchar(ch[t--]);
    putchar(\n);
}

void work1(){
    int x,y;
    int cnt=0;
    for(int i=1;i<=m;++i){
        x=read(); y=read();
        for(cnt=1;cnt<=y;++cnt){
            x=e[a[x].y].id;
        }
        put(x);
    }
}

int dfs(int x){
    num++;
    op[x]=cnt;
    a[x].dfn=num;
    a1[x].dfn=num;
    a1[x].op=cnt;
    int Next=e[a[x].y].id;
    if(!op[Next]) dfs(Next);
}

bool mycmp(hh x,hh y){
    return (x.op<y.op ||x.op==y.op && x.dfn<y.dfn);
}

void work2(){
    for(int i=1;i<=n;++i){
        if(!op[i]){
            num=0;
            cnt++;
            int x=i;
            while(!op[x]){
                op[x]=cnt;
                num++;
                a[x].dfn=num; a1[x].dfn=num;
                a1[x].op=cnt;
                x=e[a[x].y].id;
            }
            kuai[cnt]=num;
        }
    }
    sort(a1+1,a1+n+1,mycmp);
    for(int i=1;i<=n;++i){
        if(a1[i].op==a1[i-1].op) a1[i].s=a1[i].s;
        else{
            a1[i].s=i;
            start[a1[i].op]=i;
        }
    }
    int x,y;
    for(int i=1;i<=m;++i){
        x=read(); y=read();
        y+=a[x].dfn-1;
        int z=op[x];
        y%=kuai[z];
        int s=start[op[x]]+y;
        put(a1[s].id);
    }
}

int main(){
    freopen("position.in","r",stdin);
    freopen("position.out","w",stdout);
    
    n=read(); m=read();
    int x,y;
    for(int i=1;i<=n;++i){
        x=read(); y=read();
        e[x].y=y; e[x].id=i;
        a[i].x=x; a[i].y=y;
        a1[i].id=i;
    }
    if(n<=20) work1();
    else work2();
    
    fclose(stdin);fclose(stdout);
    return 0;
}

T3:給一個圖,邊權為1,現要求從s1到t1不超過l1,從s2到t2不超過l2,求最多能刪除多少邊

求出每兩個點之間的距離,然後枚舉s1->t1,s2->t2的重疊的邊,在剩下的圖中盡量選用這些重疊的邊,這樣就能保證圖中刪掉的邊是最多的

#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;

const int MAXN=3010;
struct hehe{
    int y,next;
}e[10000];
int n, m,s1, t1, l1,s2, t2, l2,dis[MAXN][MAXN],lin[MAXN],len=0;
bool vis[MAXN];

inline void insert(int x,int y){
    e[++len].next=lin[x]; lin[x]=len;
    e[len].y=y;
}

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==-) f=-1; ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch-0); ch=getchar();}
    return x*f;
}

void bfs(){
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        queue<int>q;
        q.push(i);
        vis[i]=1;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int j=lin[x];j;j=e[j].next){
                int y=e[j].y;
                if(!vis[y]){
                    vis[y]=1;
                    dis[i][y]=dis[i][x]+1;
                    q.push(y);
                }
            }
        }
    }
}

bool check(int s1, int t1, int s2, int t2, int i, int j){
    return dis[s1][i]+dis[i][j]+dis[j][t1]<=l1 && dis[s2][i]+dis[i][j]+dis[j][t2]<=l2;
}

int main(){
    freopen("destroy.in","r",stdin);
    freopen("destroy.out","w",stdout);
    n=read(); m=read();
    int x,y;
    for (int i = 1; i <= m; i++){
        x=read(); y=read();
        insert(x,y);
        insert(y,x);
    }
    s1=read(); t1=read(); l1=read();
    s2=read(); t2=read(); l2=read();
    bfs();
    int ans=dis[s1][t1]+dis[s2][t2];
    if(dis[s1][t1]>l1 || dis[s2][t2]>l2){
        cout<<"-1"<<endl;
    }
    else{
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                if(check(s1,t1,s2,t2,i,j)){
                    ans = min(ans,dis[s1][i]+dis[i][j]+dis[j][t1]+dis[s2][i]+dis[j][t2]);
                }
                if(check(t1,s1,t2,s2,i,j)){
                    ans = min(ans,dis[t1][i]+dis[i][j]+dis[j][s1]+dis[t2][i]+dis[j][s2]);
                }
                if(check(s1,t1,t2,s2,i,j)){
                    ans = min(ans,dis[s1][i]+dis[i][j]+dis[j][t1]+dis[t2][i]+dis[j][s2]);
                }
                if(check(t1,s1,s2,t2,i,j)){
                    ans = min(ans,dis[t1][i]+dis[i][j]+dis[j][s1]+dis[s2][i]+dis[j][t2]);
                }
            }
        }
        cout<<m-ans<<endl;
    }
    return 0;
}

T4emmmm

題目看不懂,題解看不懂,標程看不懂........

10-20