码迷,mamicode.com
首页 > 其他好文 > 详细

20160403~20160409

时间:2016-04-17 13:11:53      阅读:352      评论:0      收藏:0      [点我收藏+]

标签:

20160405:

1、bzoj1306 http://www.lydsy.com/JudgeOnline/problem.php?id=1306

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 using namespace std;
 6 
 7 int s2[10],ans[10],tot,n,sz;
 8 void dfs(int x,int y,int z){
 9     if(z==sz){inc(i,1,n)if(s2[i]!=ans[i])return; tot++; return;}if(x>n||y>n)return;
10     if(y!=n||(y==n&&ans[x]-s2[x]==3)){
11         s2[x]+=3;
12         if(s2[x]+3*(n-y)>=ans[x]&&s2[y]+3*(n-x)>=ans[y]&&s2[x]<=ans[x]&&s2[y]<=ans[y])y==n?dfs(x+1,x+2,z+1):dfs(x,y+1,z+1);
13         s2[x]-=3;
14     }
15     if(y!=n||(y==n&&ans[x]-s2[x]==1)){
16         s2[x]++; s2[y]++;
17         if(s2[x]+3*(n-y)>=ans[x]&&s2[y]+3*(n-x)>=ans[y]&&s2[x]<=ans[x]&&s2[y]<=ans[y])y==n?dfs(x+1,x+2,z+1):dfs(x,y+1,z+1);
18         s2[x]--; s2[y]--;
19     }
20     if(ans[x]==s2[x]||y!=n){
21         s2[y]+=3;
22         if(s2[x]+3*(n-y)>=ans[x]&&s2[y]+3*(n-x)>=ans[y]&&s2[x]<=ans[x]&&s2[y]<=ans[y])y==n?dfs(x+1,x+2,z+1):dfs(x,y+1,z+1);
23         s2[y]-=3;
24     }
25 }
26 int main(){
27     scanf("%d",&n); inc(i,1,n)scanf("%d",&ans[i]);
28     memset(s2,0,sizeof(s2)); tot=0; sz=(n*n-n)>>1;
29     dfs(1,2,0); printf("%d",tot);
30 }
View Code

题解:爆搜,加入各种奇怪剪枝,比如:剩下的比赛全赢分数都不到要求就返回、当前分数超过了要求……还有一个重要的就是如果当前已经是最后一场就直接算出比赛结果,这个剪枝虽然表面上没什么用但实际上可以把程序从TLE的边缘拯救回来。这种题对我这种从不鸟常数的就是灾难。

20160406:

2、bzoj2662 http://www.lydsy.com/JudgeOnline/problem.php?id=2662

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <queue>
 5 #define INF 0x3fffffff
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 #define turn(x,y) (y-1)*n+x
 8 using namespace std;
 9 
10 struct e{int t,w,n;}; int ess,g[100]; e es[200000];
11 void pe(int f,int t,int w){es[++ess]=(e){t,w,g[f]}; g[f]=ess;}
12 int n,m,k,s,t,d[100][100]; bool inq[100][100];
13 struct nd{int x,y;}; queue <nd> q;
14 void spfa(){
15     while(! q.empty())q.pop(); inc(i,1,n)inc(j,1,k+1)d[i][j]=INF;
16     d[1][1]=0; q.push((nd){1,1}); inq[1][1]=1;
17     while(! q.empty()){
18         nd x=q.front(); q.pop(); inq[x.x][x.y]=0;
19         for(int i=g[x.x];i;i=es[i].n)if(d[es[i].t][x.y]>d[x.x][x.y]+es[i].w){
20             d[es[i].t][x.y]=d[x.x][x.y]+es[i].w;
21             if(! inq[es[i].t][x.y])q.push((nd){es[i].t,x.y}),inq[es[i].t][x.y]=1;
22         }
23         if(x.y<=k)for(int i=g[x.x];i;i=es[i].n)if(d[es[i].t][x.y+1]>d[x.x][x.y]+(es[i].w>>1)){
24             d[es[i].t][x.y+1]=d[x.x][x.y]+(es[i].w>>1);
25             if(! inq[es[i].t][x.y+1])q.push((nd){es[i].t,x.y+1}),inq[es[i].t][x.y+1]=1;
26         }
27     }
28 }
29 int main(){
30     scanf("%d%d%d",&n,&m,&k); ess=0; memset(g,0,sizeof(g));
31     inc(i,1,m){
32         int a,b,c;scanf("%d%d%d",&a,&b,&c); pe(a,b,c),pe(b,a,c);
33     }
34     spfa(); int min=INF; inc(i,1,k+1)if(d[n][i]<min)min=d[n][i];
35     printf("%d",min);
36     return 0;    
37 }
View Code

题解:分层图最短路。这道题数据弱,可以按次数拆点,但下一道题就不行了,正解是在作spfa时“拆点”,把d弄成二维数组。虽然感觉上是一样的,但时间却相差很大,不知道为什么。

3、bzoj2763 http://www.lydsy.com/JudgeOnline/problem.php?id=2763

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <queue>
 5 #define INF 0x3fffffff
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 #define turn(x,y) (y-1)*n+x
 8 using namespace std;
 9 
10 struct e{int t,w,n;}; int ess,g[15000]; e es[200000];
11 void pe(int f,int t,int w){es[++ess]=(e){t,w,g[f]}; g[f]=ess;}
12 int n,m,k,s,t,d[15000][11]; bool inq[15000][11];
13 struct nd{int x,y;}; queue <nd> q;
14 void spfa(){
15     while(! q.empty())q.pop(); inc(i,0,n-1)inc(j,1,k+1)d[i][j]=INF;
16     d[s][1]=0; q.push((nd){s,1}); inq[s][1]=1;
17     while(! q.empty()){
18         nd x=q.front(); q.pop(); inq[x.x][x.y]=0;
19         for(int i=g[x.x];i;i=es[i].n)if(d[es[i].t][x.y]>d[x.x][x.y]+es[i].w){
20             d[es[i].t][x.y]=d[x.x][x.y]+es[i].w; if(! inq[es[i].t][x.y])q.push((nd){es[i].t,x.y}),inq[es[i].t][x.y]=1;
21         }
22         if(x.y<=k)for(int i=g[x.x];i;i=es[i].n)if(d[es[i].t][x.y+1]>d[x.x][x.y]){
23             d[es[i].t][x.y+1]=d[x.x][x.y]; if(! inq[es[i].t][x.y+1])q.push((nd){es[i].t,x.y+1}),inq[es[i].t][x.y+1]=1;
24         }
25     }
26 }
27 int main(){
28     scanf("%d%d%d%d%d",&n,&m,&k,&s,&t); ess=0; memset(g,0,sizeof(g));
29     inc(i,1,m){
30         int a,b,c;scanf("%d%d%d",&a,&b,&c); pe(a,b,c),pe(b,a,c);
31     }
32     spfa(); int min=INF;
33     inc(i,1,k+1)if(d[t][i]<min)min=d[t][i];
34     printf("%d",min);
35     return 0;    
36 }
View Code

题解:同上,但这次乱搞会TLE,本弱太弱了!

4、bzoj2038 http://www.lydsy.com/JudgeOnline/problem.php?id=2038

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define ll long long
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 using namespace std;
 8 
 9 struct nd1{
10     int l,pl,r,id; ll ans;
11 };
12 bool cmp1(nd1 a,nd1 b){
13     if(a.pl!=b.pl)return a.pl<b.pl; if(a.r!=b.r)return a.r<b.r;
14     return a.l<b.l;
15 }
16 bool cmp2(nd1 a,nd1 b){
17     return a.id<b.id;
18 }
19 nd1 a1[100000];int col[100000],pos[100000],n,m,l,r;ll ans,s[100000];
20 inline void update(int x,int y){
21     ans-=(s[col[x]]*(s[col[x]]-1));s[col[x]]+=(ll)y;ans+=(s[col[x]]*(s[col[x]]-1));
22 }
23 ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
24 int main(){
25     scanf("%d%d",&n,&m); inc(i,1,n)scanf("%d",&col[i]); int sz=(int)sqrt(n);
26     inc(i,1,n)pos[i]=(i-1)/sz+1;
27     inc(i,1,m){
28         int a,b;scanf("%d%d",&a,&b);a1[i]=(nd1){a,pos[a],b,i,0};
29     }
30     sort(a1+1,a1+1+m,cmp1); l=1; r=0; ans=0; memset(s,0,sizeof(s));
31     inc(i,1,m){
32         while(r<a1[i].r)update(r+1,1),r++;
33         while(l>a1[i].l)update(l-1,1),l--;
34         while(r>a1[i].r)update(r,-1),r--;
35         while(l<a1[i].l)update(l,-1),l++;
36         a1[i].ans=ans;
37     }
38     sort(a1+1,a1+1+m,cmp2); 
39     inc(i,1,m){
40         if(a1[i].ans==0)printf("0/1\n");else{
41             ll a2=gcd(a1[i].ans,(ll)(a1[i].r-a1[i].l+1)*(a1[i].r-a1[i].l));
42             printf("%lld/%lld\n",a1[i].ans/a2,(ll)(a1[i].r-a1[i].l+1)*(a1[i].r-a1[i].l)/a2);
43         }
44     }
45     return 0;
46 }
View Code

题解:不知道要用什么数据结构,但是可以用一个全局的数组保存每个颜色当前数量,使由区间[l,r]推出[l,r±1]的答案和[l±1,r]的复杂度为O(1),对这种问题,可以用复杂度为O(nsqrt(n))的莫队算法解决。

莫队算法是一种离线算法,将询问按某种顺序排序,使得均摊复杂度为O(nsqrt(n)),那怎么排序呢?如果按左端点排序,那么r将有可能多次大幅度摆动,使复杂度退化成O(n^2),正解是对端点分块,让后按左端点所在块为第一关键字排序,右端点为第二关键字排序。这样子当两个询问l在同一块时,l只有可能移sqrt(n)次。l在同一块的多次询问q只能右移n次,l在不同块时r可能左移n次,但因为只有sqrt(n)块,所以需移n次的操作都只有sqrt(n)次,因此均摊复杂度是O(sqrt(n))。所有的均摊复杂度都是玄学……

因为中间结果没有强制转化成long long,wa了好几发,本弱太弱了!

20160407:

5、bzoj3190 http://www.lydsy.com/JudgeOnline/problem.php?id=3190

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define eps 1e-8
 6 using namespace std;
 7 
 8 struct nd{
 9     int s,v,id;
10     bool operator < (const nd& a)const{
11         if(v!=a.v)return v<a.v; return s<a.s;
12     }
13 };
14 double solve(nd a,nd b){
15     return (double)(a.s-b.s)/(double)(b.v-a.v);
16 }
17 nd nds[20000],s[20000]; int ans[20000],n,tp;
18 int main(){
19     scanf("%d",&n); inc(i,1,n)scanf("%d",&nds[i].s),nds[i].id=i; inc(i,1,n)scanf("%d",&nds[i].v); sort(nds+1,nds+1+n);
20     tp=1;s[tp]=nds[1];ans[tp]=nds[1].id;
21     inc(i,2,n){
22         while(tp>=1&&solve(s[tp],nds[i])<-eps)tp--;
23         while(tp>=2&&solve(s[tp-1],s[tp])>solve(s[tp],nds[i]))tp--;
24         s[++tp]=nds[i]; ans[tp]=nds[i].id;
25     }
26     sort(ans+1,ans+1+tp); printf("%d\n",tp);
27     inc(i,1,tp){
28         i==tp?printf("%d",ans[i]):printf("%d ",ans[i]);
29     }
30     return 0;
31 }
View Code

题解:有人说是类似线性规划,用半平面交,反正我不会,数学考试是线性规划也错得一塌糊涂QAQ。

黄学长用的是维护斜率的方法,按照斜率排个序,依次插入一个单调栈,如果栈顶不满足XX条件(说不清楚,画个图)就弹掉,最后留在栈里的就是答案。

6、bzoj1007 http://www.lydsy.com/JudgeOnline/problem.php?id=1007

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define eps 1e-8
 7 using namespace std;
 8 
 9 struct nd{
10     int a,b,id;
11     bool operator < (const nd& x)const{
12         if(a!=x.a)return a<x.a; return b<x.b;
13     }
14 };
15 double solve(nd a,nd b){
16     return (double)(a.b-b.b)/(double)(b.a-a.a);
17 }
18 nd nds[100000],s[100000]; int ans[100000],n,tp;
19 int main(){
20     scanf("%d",&n);inc(i,1,n)scanf("%d",&nds[i].a),scanf("%d",&nds[i].b),nds[i].id=i; sort(nds+1,nds+1+n);
21     tp=1;s[tp]=nds[1];ans[tp]=nds[1].id;
22     inc(i,2,n){
23         if(nds[i].a-s[tp].a==0)tp--;
24         while(tp>=2&&solve(s[tp-1],s[tp])>=solve(s[tp],nds[i]))tp--;
25         s[++tp]=nds[i]; ans[tp]=nds[i].id;
26     }
27     sort(ans+1,ans+1+tp);inc(i,1,tp)printf("%d ",ans[i]);
28     return 0;
29 }
View Code

题解:和上一道差不多,但是因为是比较随意的直线,所以还要多一些判断条件。

20160408:

7、bzoj3289 http://www.lydsy.com/JudgeOnline/problem.php?id=3289

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define lowbit(a) a&(-a)
 7 #define ll long long
 8 using namespace std;
 9 
10 struct nd1{int x,y;};
11 bool cmp1(nd1 a,nd1 b){return a.x<b.x;}
12 struct nd2{int l,pl,r; ll ans; int id;};
13 bool cmp2(nd2 a,nd2 b){if(a.pl!=b.pl)return a.pl<b.pl; if(a.r!=b.r)return a.r<b.r; return a.l<b.l;}
14 bool cmp3(nd2 a,nd2 b){return a.id<b.id;}
15 ll c[100000],ans,l,r; int n,q,ls[100000],pos[100000]; nd1 f[100000]; nd2 ask[100000];
16 inline void add(int x,ll y){while(x<=n)c[x]+=y,x+=lowbit(x);}
17 inline ll query(int x){ll qy=0; while(x>=1)qy+=c[x],x-=lowbit(x); return qy;}
18 int main(){
19     scanf("%d",&n); inc(i,1,n)scanf("%d",&f[i].x),f[i].y=i; sort(f+1,f+n+1,cmp1);
20     inc(i,1,n)ls[f[i].y]=i; int sz=(int)sqrt(n); inc(i,1,n)pos[i]=(i-1)/sz+1;
21     scanf("%d",&q); inc(i,1,q){int a,b; scanf("%d%d",&a,&b); ask[i]=(nd2){a,pos[a],b,0,i};}
22     sort(ask+1,ask+1+q,cmp2); memset(c,0,sizeof(c)); ans=0; l=1; r=0;
23     inc(i,1,q){
24         while(r<ask[i].r){int x=r+1; x=n-ls[x]; ll a1=query(x); ans+=a1; add(x+1,1); r++;}
25         while(l>ask[i].l){int x=l-1; x=n-ls[x]; ll a1=(r-l+1)-query(x); ans+=a1; add(x+1,1); l--;}
26         while(r>ask[i].r){int x=r; x=n-ls[x]; ll a1=query(x); ans-=a1; add(x+1,-1); r--;}
27         while(l<ask[i].l){int x=l; x=n-ls[x]; ll a1=(r-l)-query(x); ans-=a1; add(x+1,-1); l++;}
28         ask[i].ans=ans;
29     }
30     sort(ask+1,ask+1+q,cmp3); inc(i,1,q)printf("%lld\n",ask[i].ans);
31     return 0;
32 }
View Code

题解:还是莫队,但是转移的时候用树状数组维护逆序对个数,总复杂度为O(nsqrt(n)log2n)。

因为是从大到小插入的,所以维护时要用r-l+1减。

8、bzoj2456 http://www.lydsy.com/JudgeOnline/problem.php?id=2456

技术分享
 1 #include <cstdio>
 2 using namespace std;
 3 int main(){
 4     int n,x,t,tot; tot=0; scanf("%d",&n);
 5     while(n--){
 6         scanf("%d",&x); 
 7         if(tot==0)t=x,tot=1;else if(x==t)tot++;else tot--;
 8     }
 9     printf("%d",t);
10 }
View Code

题解:注意空间只有1M,显然不能开数组。用两个变量,一个存“当前数”,另一个存“当前数”的个数,如果读入的数与“当前数”相同就个数加一,如果不同就减一。如果个数减到0就换“当前数”为现在读入的数。因为如果那个“众数”个数超过ndiv2,所以一定不会被其他数抵消完,能够“坚持”到最后,所以答案就是最后的那个“当前数”。思路真巧。

20160403~20160409

标签:

原文地址:http://www.cnblogs.com/YuanZiming/p/5400687.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!