2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016)

来源:互联网 发布:skype for mac 10.8.4 编辑:程序博客网 时间:2024/06/07 05:55

链接:http://codeforces.com/gym/101174


A.Within Arm's Reach

(占坑)

B.Bribing Eve

题解:

这道题看网上有dalao通过旋转卡壳非常优雅的过了啊。。。

我的做法比较蠢。。。这个问题可以转换为二维平面内向量向一条不定的直线投影,比较投影的大小问题,然后平面上的向量可以分为,投影一定大的,一定小的,投影一定相等的(重点),投影不确定的,然后计算,在直线不确定的情况下,投影大于目标向量的向量个数的最大最小值,可以发现,向量落在目标向量左上方的向量集,数量单调递增的,向量落在目标向量右下方的向量集,数量是单调递减的,然后对两种情况分别处理就好。

复杂度O(nlogn)

#include<bits/stdc++.h>using namespace std;const int MAXN=1e5+5;const double pi=acos(-1.0);const double eps=1e-8;int n,mx=0,mi=0,equ=0;struct node{int x,y;}sv[MAXN],zero;vector<node> svL,svR;vector<double> L,R;double getdis(node a,node b){double ret=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));return ret;}double angle(double A,double B,double C){double ret=((A*A)+(B*B)-(C*C))/(2*A*B);return pi/2-acos(ret);}double get(node a,node b){double C=getdis(a,zero);double B=getdis(b,zero);double A=getdis(a,b);return angle(A,B,C);}int Mx=0,Mi=1e9;void getans(){int l,r,Lm,Rm;int ret=0,k=0;double now;Lm=L.size(),Rm=R.size();l=0,r=0;Mx=Rm,Mi=Rm;k=Rm;while(l<L.size()||r<R.size()){now=1e9;if(l<L.size())now=min(L[l],now);if(r<R.size())now=min(R[r],now);while(l<Lm&&now+eps>L[l]){l++;k++;}Mx=max(Mx,k);while(r<Rm&&now+eps>R[r]){r++;k--;}Mx=max(Mx,k);}l=0,r=0;k=Rm;while(l<L.size()||r<R.size()){now=1e9;if(l<L.size())now=min(L[l],now);if(r<R.size())now=min(R[r],now);while(r<Rm&&now+eps>R[r]){r++;k--;}Mi=min(Mi,k);while(l<Lm&&now+eps>L[l]){l++;k++;}Mi=min(Mi,k);}}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);zero.x=zero.y=0;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d%d",&sv[i].x,&sv[i].y);}for(int i=2;i<=n;i++){if(sv[i].x>sv[1].x&&sv[i].y>sv[1].y){mx++;}else if(sv[i].x==sv[1].x&&sv[i].y==sv[1].y){equ++;}else if(sv[i].x<=sv[1].x&&sv[i].y>=sv[1].y){svL.push_back(sv[i]);}else if(sv[i].x>=sv[1].x&&sv[i].y<=sv[1].y){svR.push_back(sv[i]);}}for(int i=0;i<svR.size();i++){double r1=atan2(svR[i].y,svR[i].x);double r2=get(sv[1],svR[i]);R.push_back(r1+r2);}for(int i=0;i<svL.size();i++){double r1=atan2(svL[i].y,svL[i].x);double r2=get(sv[1],svL[i]);L.push_back(r1-r2);}sort(R.begin(),R.end());sort(L.begin(),L.end());getans();printf("%d %d\n",Mi+mx+1,(Mx+mx+equ+1));return 0;}


C.Candle Box

题解:

水题,模拟搞就好。

#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#include<map>#include<queue>using namespace std;int x[1010],y[1010];void init(){    memset(x,0,sizeof(x));    memset(y,0,sizeof(y));    for(int i = 4;i<=1000;i++)        x[i] = x[i-1]+i;    for(int i = 3;i<=1000;i++)        y[i] = y[i-1]+i;}int main(){    int d,a,b;    init();    while(scanf("%d%d%d",&d,&a,&b)!=EOF){        int minn = 100000;        for(int i = d;i<=900;i++)            if(x[i]+y[i-d]==a+b)                minn = min(minn,abs(a-x[i]));        printf("%d\n",minn);    }}


D.Dinner Bet

(占坑)

E.Passwords

题解:

AC自动机+DP?貌似是这么做的?

#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<queue>#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#include<map>#include<queue>#include<cctype>typedef long long LL;using namespace std;#define MOD 1000003#define CBEGIN 'a'#define SNUM 26char inputs[30];bool vis[1005];int ids;struct node{int count;int id;struct node * next[SNUM];struct node * fail;void init();}*roots, *tb[1005];void node::init(){for (int i = 0; i<SNUM; i++){next[i] = NULL;}count = 0;id = ids;tb[id] = this;ids++;fail = NULL;}void insert(char *str, node*root){node * p = root;for (int k = 0; str[k]; k++){int pos = str[k] - CBEGIN;if (p->next[pos] == NULL){p->next[pos] = new node;p->next[pos]->init();p = p->next[pos];}else{p = p->next[pos];}}p->count = 1;}void getfail(node * root){node * p = root, *son, *temp;queue<struct node*>que;que.push(p);while (!que.empty()){temp = que.front();que.pop();for (int i = 0; i<SNUM; i++){son = temp->next[i];if (son != NULL){if (temp == root){son->fail = root;}else{p = temp->fail;while (p){if (p->next[i]){son->fail = p->next[i];break;}p = p->fail;}if (!p){son->fail = roots;}}que.push(son);if (son->fail->count || son->count){son->count = 1;}}else{son = temp;while (son){if (son->next[i] != NULL){temp->next[i] = son->next[i];break;}son = son->fail;}if (!son){temp->next[i] = roots;}}}}}int tran[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 'o' - 'a', 'i' - 'a', -1, 'e' - 'a', -1, 's' - 'a', -1, 't' - 'a', -1, -1 };long long dp[22][8][1005];long long ans = 0;int main(){//ios::sync_with_stdio(false);int l, r;cin >> l >> r;int n;cin >> n;roots = new node;roots->init();for (int i = 0; i<n; i++){cin >> inputs;for (int j = 0; inputs[j]; j++){if (isupper(inputs[j])){inputs[j] = tolower(inputs[j]);}else if (isdigit(inputs[j])){switch (inputs[j]){case '0':inputs[j] = 'o';break;case '1':inputs[j] = 'i';break;case '3':inputs[j] = 'e';break;case '5':inputs[j] = 's';break;case '7':inputs[j] = 't';break;}}}//cout<<input<<"\n";insert(inputs, roots);}getfail(roots);dp[0][0][0] = 1;for (int i = 0; i < r; i++){for (int j = 0; j < 8; j++){for (int k = 0; k<ids; k++){if (tb[k]->count){continue;}for (int z = 0; z<62; z++){int mov;if (z<26){mov = 0;}else if (z<52){mov = 1;}else{mov = 2;}if (tran[z] == -1){dp[i + 1][j | (1 << mov)][0] += dp[i][j][k];dp[i + 1][j | (1 << mov)][0] %= MOD;}else{dp[i + 1][j | (1 << mov)][tb[k]->next[tran[z]]->id] += dp[i][j][k];dp[i + 1][j | (1 << mov)][tb[k]->next[tran[z]]->id] %= MOD;}}}}if (i+1 >= l && i+1 <= r){for (int j = 0; j<ids; j++){if (!tb[j]->count){ans += dp[i+1][7][j];ans %= MOD;}}}}cout << ans%MOD << "\n";//cin >> ans;return 0;}


F.Performance Review

题解:

按照dfs序建立线段树,每一段区间中维护这个区间所有元素,按照m进行排序,然后维护一个关于t 的前缀和方便查询,每次查找时在区间内二分查找结果。

建树的复杂度O(nlognlogn),查询复杂度O(lognlogn)

貌似主席树也能做?

线段树按子树算贡献,每次去除其他子树的贡献貌似更牛逼啊。。。

#include<bits/stdc++.h>using namespace std;const int MAXN=1e5+5;typedef long long ll;vector<int> E[MAXN];int m[MAXN],t[MAXN],in[MAXN],out[MAXN],id[MAXN];int In=0;int n,root;ll ans[MAXN];struct tnode{int m,t;ll sum;tnode(){}tnode(int _m,int _t):m(_m),t(_t){}bool operator < (const tnode &a)const{return m<a.m;}};struct node{vector<tnode> sv;}tree[MAXN<<2];void dfs1(int now){in[now]=++In;id[In]=now;for(int i=0;i<E[now].size();i++){int v=E[now][i];dfs1(v);}out[now]=In;}void build(int l,int r,int rt){if(l==r){tnode tmp=tnode(m[id[l]],t[id[l]]);tmp.sum=t[id[l]];tree[rt].sv.push_back(tmp);return;}for(int i=l;i<=r;i++){tree[rt].sv.push_back(tnode(m[id[i]],t[id[i]]));}sort(tree[rt].sv.begin(),tree[rt].sv.end());ll now=0;for(int i=0;i<tree[rt].sv.size();i++){now+=tree[rt].sv[i].t;tree[rt].sv[i].sum=now;}int mid=(l+r)>>1;build(l,mid,rt<<1);build(mid+1,r,rt<<1|1);}vector<tnode> :: iterator it;ll query(int L,int R,int val,int l,int r,int rt){if(L<=l&&r<=R){it=lower_bound(tree[rt].sv.begin(),tree[rt].sv.end(),tnode(val,0));if(it==tree[rt].sv.begin())return 0;elseit--;return it->sum;}int mid=(l+r)>>1;ll ret=0;if(mid>=L){ret+=query(L,R,val,l,mid,rt<<1);}if(mid<R){ret+=query(L,R,val,mid+1,r,rt<<1|1);}return ret;}void dfs2(int now){ans[now]=query(in[now],out[now],m[now],1,n,1);for(int i=0;i<E[now].size();i++){int v=E[now][i];dfs2(v);}}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++){int v;scanf("%d%d%d",&v,&m[i],&t[i]);if(v==-1)root=i;elseE[v].push_back(i);}dfs1(root);build(1,n,1);dfs2(root);for(int i=1;i<=n;i++){printf("%lld\n",ans[i]);}return 0;}


G.Cairo Corridor

题解:

XJB暴力。。。建图比较难。。。其他的分情况考虑切点问题,如果不是切点,判断去掉后能否到达四个边界

#include<bits/stdc++.h>using namespace std;const int MAXN=505;const int MAXM=505*505*2*10;struct Edge{    int to,next;}edge[MAXM];int head[MAXN*MAXN],tot;int Low[MAXN*MAXN],DFN[MAXN*MAXN],Stack[MAXN*MAXN];int Index,top;bool Instack[MAXN*MAXN];bool cut[MAXN*MAXN];bool book[MAXN*MAXN];bool mp[MAXN*MAXN];int border[MAXN*MAXN];int ID[MAXN][MAXN][2];int id,n,m,ans,now;void addedge(int u,int v){if(u==-1||v==-1||mp[u]||mp[v])return ;    edge[tot].to=v;edge[tot].next=head[u];    head[u]=tot++;}void init(){tot=0;id=0;ans=-1;memset(head,-1,sizeof(head));memset(cut,0,sizeof(cut));memset(ID,-1,sizeof(ID));memset(border,0,sizeof(border));memset(mp,false,sizeof(mp));memset(book,false,sizeof(book));}vector<int> Q;void Tarjan(int u,int pre){     int v;    Low[u]=DFN[u]=++Index;    Stack[top++]=u;    Instack[u]=true;book[u]=true;Q.push_back(u);now|=border[u];    int son=0;    for(int i=head[u];i!=-1;i=edge[i].next)    {        v=edge[i].to;        if(v==pre)continue;        if(!DFN[v])         {             son++;            Tarjan(v,u);            if(Low[u]>Low[v])Low[u]=Low[v];            if(u!=pre&&Low[v]>=DFN[u])//涓嶆槸鏍戞牴            {                cut[u]=true;            }        }        else if(Low[u]>DFN[v])             Low[u]=DFN[v];    }    if(u==pre&&son>1)cut[u]=true;    Instack[u]=false;    top--;}void Solve(int at){memset(DFN,0,sizeof(DFN));memset(Instack,false,sizeof(Instack));Index=top=now=0;Q.clear();Tarjan(at,at);}void build(){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){int u,v;if((i+j)%2){u=ID[i][j][0];v=ID[i][j-1][1];addedge(u,v);v=ID[i][j+1][0];addedge(u,v);v=ID[i-1][j][0];addedge(u,v);v=ID[i-1][j][1];addedge(u,v);u=ID[i][j][1];v=ID[i][j-1][1];addedge(u,v);v=ID[i][j+1][0];addedge(u,v);v=ID[i+1][j][0];addedge(u,v);v=ID[i+1][j][1];addedge(u,v);}else{u=ID[i][j][0];v=ID[i][j-1][0];addedge(u,v);v=ID[i][j-1][1];addedge(u,v);v=ID[i-1][j][1];addedge(u,v);v=ID[i+1][j][0];addedge(u,v);u=ID[i][j][1];v=ID[i][j+1][0];addedge(u,v);v=ID[i][j+1][1];addedge(u,v);v=ID[i-1][j][1];addedge(u,v);v=ID[i+1][j][0];addedge(u,v);}u=ID[i][j][0],v=ID[i][j][1];addedge(u,v);addedge(v,u);}}for(int j=1;j<=m;j++){int u=ID[1][j][0],v=ID[1][j][1];if(((1+j)&1)==0){border[u]|=(1);border[v]|=(1);}else{border[u]|=(1);}u=ID[n][j][0],v=ID[n][j][1];if(((n+j)&1)==0){border[u]|=(1<<1);border[v]|=(1<<1);}else{border[v]|=(1<<1);}}for(int i=1;i<=n;i++){int u=ID[i][1][0],v=ID[i][1][1];if(((i+1)&1)==0){border[u]|=(1<<2);}else{border[u]|=(1<<2);border[v]|=(1<<2);}u=ID[i][m][0],v=ID[i][m][1];if(((i+m)&1)==0){border[v]|=(1<<3);}else{border[u]|=(1<<3);border[v]|=(1<<3);}}}void judge(){int Bo=0;if(now!=(1<<4)-1)return;for(int i=0;i<(int)Q.size();i++){int at=Q[i];if(!cut[at]){Bo=0;for(int j=0;j<(int)Q.size();j++){if(j==i)continue;Bo|=border[Q[j]];}if(Bo==now)return ;}}ans=max(ans,(int)Q.size());}void solve(){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){int u=ID[i][j][0];if(!book[u]&&!mp[u]){Solve(u);judge();}u=ID[i][j][1];if(!book[u]&&!mp[u]){Solve(u);judge();}}}if(ans==-1){printf("NO MINIMAL CORRIDOR\n");}else{printf("%d\n",ans);}}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int T;scanf("%d\n",&T);while(T--){init();scanf("%d %d\n",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){char u,v;scanf("%c%c",&u,&v);u-='0',v-='0';ID[i][j][0]=id++;ID[i][j][1]=id++;mp[ID[i][j][0]]=u,mp[ID[i][j][1]]=v;//printf("%d %d\n",u,v);}getchar();}build();solve();}return 0;}


H.Pascal's Hyper-Pyramids

题解:

暴力搜索?貌似32*32也就才6000多个答案。

#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#include<map>#include<queue>typedef long long LL;using namespace std;int D,H;LL ans[100010];LL ct;struct node{    char data[34];    bool operator< (const node & right)const    {        for(int i =0;i<34;i++)        {            if(data[i]!=right.data[i])            {                return data[i]<right.data[i];            }        }        return 0;    }};map<node,LL>mp;void cou(node x){    node y;    LL cnt = 0;    if(mp[x]>0)        return;    for(int i = 0;i < D;i++){        if(x.data[i]==0)            continue;        if(i==0||(i>0&&x.data[i]!=x.data[i-1])){           y = x;           y.data[i] -= 1;           cnt = mp[y];        }        mp[x] += cnt;    }}void prin(node x){    ans[ct++] = mp[x];}void dfs(int c,int now,int sum,node x){    if(sum==c&&now==D){        cou(x);        if(c==H-1)         prin(x);        return;    }    if(sum>c||now>=D)        return;    for(int i = x.data[now-1];i<=H;i++){        x.data[now] = i;        dfs(c,now+1,sum+i,x);    }}int main(){    scanf("%d%d",&D,&H);    node x;    ct = 0;    memset(x.data,0,sizeof(x.data));    x.data[D-1] = 0;    mp[x] = 1;    for(int i = 1;i < H;i++)        for(int j = 0;j < H;j++){            x.data[0] = j;            dfs(i,1,j,x);        }    //printf("%d\n",ct);    sort(ans,ans+ct);    for(int i = 0;i < ct;i++)        if(i==0||(i>0&&ans[i]>ans[i-1]))            printf("%lld\n",ans[i]);    return 0;}


I.The White Rabbit Pocket Watch

题解:

首先%13系下的高斯消元解出所有路径的长度(虽然不知道为啥一定有唯一解。。。),然后floyd求最短路就好,感觉这道题有板就能过啊?(还有floyd别写错啊。。。)感觉难度不大啊,早看的话能过。

#include<bits/stdc++.h>#define xx first#define yy second#define mp make_pairusing namespace std;typedef long long ll;const int MOD=13;const int MAXN=205;ll a[505][MAXN*MAXN],x[505],dis[MAXN][MAXN];int ID[MAXN][MAXN],cnt=0;ll qpow(ll a,ll b){ll ans=1;a%=MOD;    for(ll i=b;i;i>>=1,a=a*a%MOD)        if(i&1)ans=ans*a%MOD;    return ans;}void Gauss(int equ,int var){int row,max_r,col;for(row=0,col=0;col<var&&row<equ;col++,row++){max_r=row;for(int i=row+1;i<equ;i++){if(abs(a[i][col])>abs(a[max_r][col])){max_r=i;}}if(!a[max_r][col]){row--;continue;}if(row!=max_r){for(int j=0;j<=var;j++){swap(a[row][j],a[max_r][j]);}}for(int i=row+1;i<equ;i++){if(a[i][col]){ll lcm=a[i][col]/__gcd(a[i][col],a[row][col])*a[row][col];ll t1=lcm/a[i][col];ll t2=lcm/a[row][col];for(int j=col;j<=var;j++){a[i][j]=((a[i][j]*t1-a[row][j]*t2)%MOD+MOD)%MOD;}}}}for(int i=var-1;i>=0;i--){x[i]=a[i][var];for(int j=i+1;j<var;j++){x[i]=((x[i]-a[i][j]*x[j])%MOD+MOD)%MOD;}x[i]=x[i]*qpow(a[i][i],MOD-2)%MOD;}}int n,A,R,T;vector<int> sv;map<int,pair<int,int> > M;int getid(int x,int y){if(ID[x][y]==-1){ID[x][y]=ID[y][x]=cnt;M[cnt]=mp(x,y);cnt++;}return ID[x][y];}int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);scanf("%d%d%d%d",&n,&A,&R,&T);memset(ID,-1,sizeof(ID));memset(dis,0x3f,sizeof(dis));memset(a,0,sizeof(a));for(int i=0;i<T;i++){int d,p,tmp;scanf("%d%d",&d,&p);sv.clear();for(int j=0;j<p;j++){scanf("%d",&tmp);sv.push_back(tmp);}for(int j=1;j<sv.size();j++){int id=getid(sv[j],sv[j-1]);a[i][id]++;a[i][id]%=MOD;}x[i]=d;}for(int i=0;i<T;i++){a[i][cnt]=x[i];}Gauss(T,cnt);for(int i=0;i<cnt;i++){int u,v;u=M[i].xx,v=M[i].yy;dis[u][v]=dis[v][u]=x[i];}for(int i=1;i<=n;i++)dis[i][i]=0;for(int k=1;k<=n;k++){for(int j=1;j<=n;j++){for(int i=1;i<=n;i++){dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);}}}printf("%d\n",dis[R][A]);return 0;}


J..Risky Lottery

(占坑)

K.Balls and Needles

题解:

队友写的,题都没看233333

#include<iostream>#include<string>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#include<map>#include<queue>using namespace std;int bcj[200005];int find(int x){    if(bcj[x]==0)    {        bcj[x]=x;    }    if(bcj[x]==x)    {        return x;    }    bcj[x]=find(bcj[x]);    return bcj[x];}void merge(int x,int y){    if(find(x)==find(y))    {        return ;    }    bcj[find(x)]=y;}struct node{    int x,y,z;    bool operator< (const node & right)const    {        if(x!=right.x)        {            return x<right.x;        }        if(y!=right.y)        {            return y<right.y;        }        return z<right.z;    }}be,ed;map<node,int>mp;map<int,int>con[200005];int beg=1;int main(){    ios::sync_with_stdio(false);    int n;    cin>>n;    int tmp;    int a,b;    int rcir=0,dcir=0;    for(int i=0;i<n;i++)    {        cin>>be.x>>be.y>>be.z;        cin>>ed.x>>ed.y>>ed.z;        if(mp.find(be)!=mp.end())        {            a=mp[be];        }        else        {            mp[be]=beg;            a=beg;            beg++;        }        if(mp.find(ed)!=mp.end())        {            b=mp[ed];        }        else        {            mp[ed]=beg;            b=beg;            beg++;        }        if(find(a)==find(b)&&a != b && con[a].find(b)==con[a].end())        {            rcir=1;        }        if(a!=b)        {            con[a][b]=1;            con[b][a]=1;        }        merge(a,b);        be.z=0;        ed.z=0;        if(mp.find(be)!=mp.end())        {            a=mp[be];        }        else        {            mp[be]=beg;            a=beg;            beg++;        }        if(mp.find(ed)!=mp.end())        {            b=mp[ed];        }        else        {            mp[ed]=beg;            b=beg;            beg++;        }        if(find(a)==find(b)&& a != b&&con[a].find(b)==con[a].end())        {            dcir=1;        }        if(a!=b)        {            con[a][b]=1;            con[b][a]=1;        }        merge(a,b);    }    if(rcir)    {        cout<<"True closed chains\n";    }    else    {        cout<<"No true closed chains\n";    }    if(dcir)    {        cout<<"Floor closed chains\n";    }    else    {        cout<<"No floor closed chains\n";    }    return 0;}



0 0