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

20160417~20160423

时间:2016-04-23 23:03:33      阅读:383      评论:0      收藏:0      [点我收藏+]

标签:

又是一周总结时间~中间有一周停了是因为本弱去准备考试了。下星期就是GDOI了,本弱还是去旅游!比赛什么的……蒟蒻早已准备退役了。

20160418:

1、bzoj3223 http://www.lydsy.com/JudgeOnline/problem.php?id=3223

题意:一个数列,支持区间翻转操作。

代码:

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define fa(x) nds[x].fa
 6 #define ch(x,y) nds[x].ch[y]
 7 #define tg(x) nds[x].tg
 8 #define v(x) nds[x].v
 9 #define sz(x) nds[x].sz
10 using namespace std;
11 
12 struct nd{int fa,ch[2],v,sz,tg;};
13 nd nds[200000]; int size,root,n,m; bool first;
14 void pushdown(int x){
15     if(! x)return; if(tg(x)){
16         if(ch(x,0)&&ch(x,1))swap(ch(x,0),ch(x,1)),tg(ch(x,0))^=1,tg(ch(x,1))^=1;else
17         if(ch(x,0))ch(x,1)=ch(x,0),ch(x,0)=0,tg(ch(x,1))^=1;else ch(x,0)=ch(x,1),ch(x,1)=0,tg(ch(x,0))^=1;
18         tg(x)^=1;
19     }
20 }
21 void update(int x){if(! x)return; sz(x)=sz(ch(x,0))+sz(ch(x,1))+1;}
22 void rotate(int x){
23     if(x==0||fa(x)==0)return;
24     int a1=fa(x),a2=fa(a1); bool a3=(x==ch(a1,1)),a4=(a1==ch(a2,1));
25     if(a2)ch(a2,a4)=x; if(ch(x,!a3))fa(ch(x,!a3))=a1; ch(a1,a3)=ch(x,!a3); ch(x,!a3)=a1; 
26     fa(x)=a2; fa(a1)=x; update(a1); update(x); if(a2)update(a2);
27 }
28 void splay(int x,int y){
29     if(x==0||y==0)return; int z=fa(y); if(y==root)root=x;
30     while(fa(x)!=z){
31         if(fa(fa(x))!=z){
32             if((x==ch(fa(x),1))^(fa(x)==ch(fa(fa(x)),1)))rotate(x);else rotate(fa(x));
33         }
34         rotate(x);
35     }
36 }
37 int build(int l,int r){
38     if(l>r)return 0;
39     ++size; int ff=size; int m=(l+r)>>1; ch(ff,0)=build(l,m-1); ch(ff,1)=build(m+1,r);
40     if(ch(ff,0))fa(ch(ff,0))=ff; if(ch(ff,1))fa(ch(ff,1))=ff;
41     v(ff)=m; tg(ff)=0; update(ff); return ff;
42 }
43 int find(int p){
44     int x=root; while(1){
45         if(x==0)return 0; pushdown(x);
46         int a1=sz(ch(x,0)); if(a1+1==p)return x;
47         if(a1+1<p)p-=(a1+1),x=ch(x,1);else x=ch(x,0);
48     }
49 }
50 void rever(int l,int r){
51     int a1=find(l-1),a2=find(r+1); splay(a2,root); 
52     if(l>1)splay(a1,ch(a2,0)),tg(ch(a1,1))^=1;else tg(ch(a2,0))=1;
53 }
54 void print(int x){
55     if(x==0)return; pushdown(x);
56     print(ch(x,0));
57     if(v(x)!=n+1)
58         if(!first)printf("%d",v(x)),first=1;else printf(" %d",v(x)); 
59     print(ch(x,1));
60 }
61 int main(){
62     //freopen("test.txt","r",stdin);
63     scanf("%d%d",&n,&m); size=0; root=build(1,n+1);
64     inc(i,1,m){
65         int a,b; scanf("%d%d",&a,&b); rever(a,b);
66     }
67     first=0; print(root);
68     return 0;
69 }
View Code

题解:splay裸题。注意涉及到区间操作的一般用splay不用treap。

2、bzoj2299 http://www.lydsy.com/JudgeOnline/problem.php?id=2299

题意:有(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问能否拼出另一个向量(x,y)。

代码:

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 long long gcd(long long a,long long b){return b==0?a:gcd(b,a%b);}
 7 inline bool check(long long x,long long y,long long z){return x%z==0&&y%z==0;}
 8 int main(){
 9     int t; scanf("%d",&t);
10     while(t--){
11         long long a,b,x,y; scanf("%lld%lld%lld%lld",&a,&b,&x,&y);
12         long long c=gcd(2*a,2*b);
13         if(check(x,y,c)||check(x+a,y+b,c)||check(x+b,y+a,c)||check(x+a+b,y+a+b,c))puts("Y");else puts("N");
14     }
15     return 0;
16 }
View Code

题解:裴蜀定理(我不会)(实际上是与解同余方程的知识相关的)。题目可以转化为用(0,2a)、(2a,0)、(0,2b)、(2b,0)拼成(x,y)、(x+a,y+b)、(x+b,y+a)、(x+a+b,y+a+b)。这样就可以列方程了。题目要求判断方程是否有解,只要求出2a、2b的gcd,然后判断目标两个数能否整除这个gcd即可。

3、bzoj3442 http://www.lydsy.com/JudgeOnline/problem.php?id=3442

题意:共有n个学生,m个学习小组,每个学生只愿意参加其中的一些学习小组,且一个学生最多参加k个学习小组。每个学生参加学习小组财务处都收一定的手续费,不同的学习小组有不同的手续费。若有a个学生参加第i个学习小组,财务处支付奖励Ci*a^2元。在参与学生(而不是每个学习小组的人数总和)尽量多的情况下,求财务处最少要支出多少钱。

代码:

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <queue>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define visit(i,j) for(int i=g[j];i!=-1;i=es[i].n)
 7 #define INF 0x3fffffff
 8 using namespace std;
 9 
10 struct e{int f,t,c,w,n;}; e es[1000000]; int ess,g[400];
11 void pe(int f,int t,int c,int w){
12     es[++ess]=(e){f,t,c,w,g[f]}; g[f]=ess; es[++ess]=(e){t,f,0,-w,g[t]}; g[t]=ess;
13 }
14 void init(){ess=-1; memset(g,-1,sizeof(g));}
15 int d[400],fr[400]; queue <int> q; bool inq[400],vis[400];
16 bool spfa(int s,int t){
17     while(! q.empty())q.pop(); memset(inq,0,sizeof(inq)); memset(vis,0,sizeof(vis));
18     inq[s]=1; d[s]=0; vis[s]=1; q.push(s);
19     while(! q.empty()){
20         int x=q.front(); q.pop(); inq[x]=0;
21         visit(i,x)if(es[i].c&&(! vis[es[i].t]||d[es[i].t]>d[x]+es[i].w)){
22             d[es[i].t]=d[x]+es[i].w; vis[es[i].t]=1; fr[es[i].t]=i;
23             if(! inq[es[i].t])inq[es[i].t]=1,q.push(es[i].t);
24         }
25     }
26     if(! vis[t])return 0;else return 1;
27 }
28 int advanced(int s,int t){
29     int a=INF; for(int i=t;i!=s;i=es[fr[i]].f)a=min(a,es[fr[i]].c);
30     int cost=0; for(int i=t;i!=s;i=es[fr[i]].f)es[fr[i]].c-=a,es[fr[i]^1].c+=a,cost+=(es[fr[i]].w*a);
31     return cost;
32 }
33 int maxflowmincost(int s,int t){
34     int cost=0; while(spfa(s,t))
35     cost+=advanced(s,t); return cost;
36 }
37 int n,m,k,s,t,a1[400]; char a3[400];
38 int main(){
39     //freopen("test.txt","r",stdin);
40     scanf("%d%d%d",&n,&m,&k); s=0; t=n+m+1; init(); inc(i,1,n)pe(s,i,k,0),pe(i,t,k-1,0);
41     inc(i,n+1,n+m){int a2; scanf("%d",&a2); inc(j,1,n)pe(i,t,1,(j*2-1)*a2);}
42     inc(i,1,m)scanf("%d",&a1[i]); inc(i,1,n){
43         scanf("%s",a3); inc(j,1,m){if(a3[j-1]==1)pe(i,n+j,1,-a1[j]);}
44     }
45     printf("%d",maxflowmincost(s,t));
46     return 0;
47 }
View Code

 题解:s连n个学生,流量为k,费用为0。每个学生向喜欢的小组的连边,流量为1,费用为手续费的相反数。每个小组向t连边,它的费用与流量的平方成正比的边,需要把它拆成k条流量为1,费用为1*ci、3*ci…(2*k-1)的边。本题的难点是要参与学生尽量多,所以我们需要每个学生至少参加一个组,因此每个学生再向t连一条流量为k-1,费用为0的边,就可以了。

4、bzoj2751 http://www.lydsy.com/JudgeOnline/problem.php?id=2751

题意:已知一个数列A对于所有的A[i]都是1~n的自然数,一些A[i]不能取一些值,求出所有可能的数列的积的和 mod 1000000007的值。

代码:

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define ll long long
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define mod 1000000007
 7 using namespace std;
 8 
 9 struct nd{
10     ll a,b;
11     bool operator < (const nd &c)const{
12         if(a!=c.a)return a<c.a;else return b<c.b;
13     }
14 };
15 ll power(ll a,ll b){
16     if(b==0)return 1; if(b==1)return a; ll c=power(a,b>>1)%mod;
17     if(b&1)return c*c%mod*a%mod;else return c*c%mod;
18 }
19 nd ns[200000];
20 int main(){
21     ll n,m,a1=0,a2,a3,a4; ll k; scanf("%lld%lld%lld",&n,&m,&k);
22     inc(i,1,k)scanf("%lld%lld",&ns[i].a,&ns[i].b); sort(ns+1,ns+k+1);
23     inc(i,1,k)if(i==1||ns[i].a!=ns[i-1].a)a1++; a2=n*(n+1)/2%mod; a3=a4=1;
24     inc(i,1,k)if(i==1||ns[i].a!=ns[i-1].a)a4=a4*a3%mod,a3=a2,a3=(a3-ns[i].b)>=0?(a3-ns[i].b)%mod:(a3-ns[i].b)+mod;
25     else if(ns[i].b!=ns[i-1].b)a3=(a3-ns[i].b)>=0?(a3-ns[i].b)%mod:(a3-ns[i].b)+mod;
26     a4=a4*a3%mod; a4=a4*power(a2,m-a1)%mod; printf("%lld",a4);
27 }
View Code

题解:题目中的n≤109实际上是109……首先推个方程s[l,r]=s[l,k]*s[k+1,r](s[l,r]表示l到r的所有l≤i≤r的a[i]的可能取值的和)因此s[1,n]等于所有a[i]的可能取值的和的乘积。因此我们先求出1到n的和,对每个约束条件按i排序,将这个和减掉约束条件中的不能取的数,就是这个a[i]所有可能取值的和。将这些a[i]乘起来,剩下的没限制的a[i]用快速幂解决。

5、bzoj2843 http://www.lydsy.com/JudgeOnline/problem.php?id=2843

题意:一些点,每个点有一个权值。有三种操作:点与点连边,单点修改权值,求两点之间路径上点的权值和(需要判输入是否合法)

6、bzoj2429 http://www.lydsy.com/JudgeOnline/problem.php?id=2429

题意:平面上N个点(任意两个点的坐标都不相同)。现已知M个猴子的最大跳跃距离,还知道N个点坐标,统计有多少个猴子可以在所有点上觅食。

7、bzoj2428 http://www.lydsy.com/JudgeOnline/problem.php?id=2428

题意:已知N个正整数,将它们分成M组,使各组数据的数值和最平均,即各组的均方差最小,求最小均方差。

技术分享

 

其中σ为均方差,-x-是各组数据和的平均值,xi为第i组数据的数值和。

8、bzoj4514 http://www.lydsy.com/JudgeOnline/problem.php?id=4514

题意:有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。若两个数字 ai、aj 满足ai 是 aj 的倍数且 ai/aj 是一个质数,那么这两个数字可以配对,并获得 ci×cj 的价值。一个数字只能参与一次配对,可以不参与配对。在获得的价值总和不小于 0 的前提下,求最多进行多少次配对。

9、bzoj2049 http://www.lydsy.com/JudgeOnline/problem.php?id=2049

题意:一些点,三种操作:点与点连边、点与点分离、询问两个点是否连通。

10、bzoj4518 http://www.lydsy.com/JudgeOnline/problem.php?id=4518

题意:n个数,分成m段使每段和的方差尽可能小。设方差是v,可证v×(m^2)是一个整数。输出v×(m^2)。

11、bzoj1264 http://www.lydsy.com/JudgeOnline/problem.php?id=1264

题意:某种序列由n种数组成,每种数在该序列中正好出现5次。对于两个这样的序列s1和s2,如果存在一个序列u同时成为s1和s2的子序列,则称u是s1和s2的公共子序列。子序列的概念:若从一个序列s中任意抽取一些数字,将它们仍按在s中的顺序排列成一个新串u,则称u是s的一个子序列。已知两个等长DNA序列s1和s2,求s1和s2最长公共子序列的长度。

20160417~20160423

标签:

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

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