10.23模擬賽
阿新 • • 發佈:2017-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(AC"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; }
對於區間[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模擬賽