10-20

比较水的题目吧

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

题目看不懂,题解看不懂,标程看不懂........

posted @ 2017-10-20 18:00  assassin灬  阅读(428)  评论(0编辑  收藏  举报