1. 程式人生 > >10.23模擬賽

10.23模擬賽

image ans img front 整數 最短路 strong font 次數

T1叉叉

題目描述

現在有一個字符串,每個字母出現的次數均為偶數。接下來我們把第一次出現的字母a和第二次出現的a連一條線,第三次出現的和四次出現的字母a連一條線,第五次出現的和六次出現的字母a連一條線...對其他25個字母也做同樣的操作。

現在我們想知道有多少對連線交叉。交叉的定義為一個連線的端點在另外一個連線的內部,另外一個端點在外部。

下圖是一個例子,共有三對連線交叉(我們連線的時候,只能從字符串上方經過)。

技術分享

輸入格式

一行一個字符串。保證字符串均由小寫字母組成,且每個字母出現次數為偶數次。

輸出格式

一個整數,表示答案。

樣例輸入

abaazooabz

樣例輸出

3

數據範圍

對於

30% 的數據,字符串長度不超過50。

對於100% 的數據,字符串長度不超過100,000。

代碼:

抽出線段計算覆蓋

技術分享
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

char s[100009];
int ans,len,cnt,pre[30];

struct E{
    int l,r;
}e[100009];

bool cmp(E a,E b){
    return a.l<b.l;
}

int main(){
    freopen(
"corss.in","r",stdin); freopen("corss.out","w",stdout); scanf("%s",s+1);len=strlen(s+1); for(int i=1;i<=len;i++){ int k=s[i]-a+1; if(pre[k]){ e[++cnt].l=pre[k]; e[cnt].r=i; pre[k]=0; continue; } pre[k]=i; } sort(e
+1,e+cnt+1,cmp); for(int i=1;i<=cnt;i++){ for(int j=i+1;j<=cnt;j++){ if(e[j].l>e[i].r)break; if(e[j].l<e[i].r&&e[j].r>e[i].r)ans++; } } printf("%d\n",ans); fclose(stdin);fclose(stdout); return 0; }
AC

對於區間[l,r]如果某個字母對於這個區間相交,那麽[1,l-1]會出現奇數次,[l,r]至少出現一次。

同理[r+1,n]出現奇數次,我們只計算[1,l-1]出現奇數次。

技術分享
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 100009
using namespace std;

char s[maxn];
int ans,len,cnt,pre[30],sum[maxn][27];

struct E{
    int l,r;
}e[maxn];

bool cmp(E a,E b){
    return a.l<b.l;
}

int main(){
//    freopen("corss.in","r",stdin);
//d    freopen("corss.out","w",stdout);
    scanf("%s",s+1);len=strlen(s+1);
    for(int i=1;i<=len;i++){
        int k=s[i]-a+1;
        for(int j=1;j<=26;j++)sum[i][j]=sum[i-1][j];
        sum[i][k]++;
        if(pre[k]){
            e[++cnt].l=pre[k];
            e[cnt].r=i;
            pre[k]=0;
            continue;
        }
        pre[k]=i;
    }
    sort(e+1,e+cnt+1,cmp);
    for(int i=1;i<=cnt;i++){
        int l=e[i].l,r=e[i].r;
        for(int j=1;j<=26;j++){
            if(sum[l-1][j]&1)
             if(sum[r-1][j]-sum[l][j])ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}
AC

T2 跳跳虎

技術分享

技術分享

技術分享

技術分享

技術分享

技術分享

技術分享

技術分享

題解:

分層圖最短路。dis數組開二維。dis[i][v]表示到i用了v個邊。

註意k很大,然而沒有什麽卵用,因為q=2000.數組開2000就好了。

代碼:

技術分享
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define maxn 1000
using namespace std;

int n,m,p,q,sumedge,k,ans;
int dis[maxn][2090],inq[maxn][2090],head[maxn];

struct node{
    int x,cnt;
};
queue<node>qq;

struct Edge{
    int x,y,z,nxt,s;
    Edge(int x=0,int y=0,int z=0,int nxt=0,int s=0):
        x(x),y(y),z(z),nxt(nxt),s(s){}
}edge[maxn*5];

void add(int x,int y,int z,int s){
    edge[++sumedge]=Edge(x,y,z,head[x],s);
    head[x]=sumedge;
}

void spfa(){
    memset(dis,0x3f,sizeof(dis));
    dis[1][0]=0;inq[1][0]=true;
    node a;a.x=1;a.cnt=0;
    qq.push(a);
    while(!qq.empty()){
        node now=qq.front();qq.pop();
        inq[now.x][now.cnt]=false;
        int x=now.x,cnt=now.cnt;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(edge[i].s==0&&cnt<k){
                if(dis[v][cnt+1]>dis[x][cnt]+edge[i].z){
                    dis[v][cnt+1]=dis[x][cnt]+edge[i].z;
                    if(inq[v][cnt+1]==0){
                        inq[v][cnt+1]=true;
                        node nxt;nxt.x=v;nxt.cnt=cnt+1;
                        qq.push(nxt);
                    }
                }
            }
            if(edge[i].s==1){
                if(dis[v][cnt]>dis[x][cnt]+edge[i].z){
                    dis[v][cnt]=dis[x][cnt]+edge[i].z;
                    if(!inq[v][cnt]){    
                        node nxt;nxt.x=v;nxt.cnt=cnt;
                        qq.push(nxt);
                        inq[v][cnt]=true;
                    }
                }
            }
        }
    }
}

int main(){
    freopen("move.in","r",stdin);
    freopen("move.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&q,&k);
    k=min(k,q);
    //n個點,m條邊,q表示通道數量,k表示能用幾次。
    for(int i=1;i<=m+q;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(i>m)add(x,y,z,0);
        else add(x,y,z,1);
    }
    spfa(); 
    ans=INF;
    for(int i=0;i<=k;i++)ans=min(ans,dis[n][i]);
    if(ans==INF)printf("-1\n");
    else printf("%d\n",ans);
    fclose(stdin);fclose(stdout);
    return 0;
}
AC

T3秀秀與布魯國

技術分享

技術分享

技術分享

技術分享

10.23模擬賽