20160417~20160423

又是一周总结时间~中间有一周停了是因为本弱去准备考试了。下星期就是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 }

题解: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 }

题解:裴蜀定理(我不会)(实际上是与解同余方程的知识相关的)。题目可以转化为用(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 }

题解: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 }

题解:题目中的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最长公共子序列的长度。

时间: 2024-10-01 16:59:33

20160417~20160423的相关文章

20160423 二维数组,锯齿数组和集合

2016-04-23  20:46:26 一.二维数组: 一维数组----豆角 二维数组----表格 1)定义: 一维数组: 数据类型[] 数组变量名 = new 数据类型[数组长度]; 数据类型[] 数组变量名 = new 数据类型[数组长度]{1,2,3....}; 2)二维数组: 数据类型[,] 数组变量名 = new 数据类型[行数,列数]; int[,] a = new int[3,4]; 赋值: a[行下标,列下标] = 值       下标都是从0开始的 取值: a[行下标,列下标

[2016-04-17][Gym][100947][I][What a Mess]

时间:2016-04-18 17:36:12 星期一 题目编号:[2016-04-17][Gym][100947][I][What a Mess] 题目大意:给定n个数字,问成整除关系的 (ai,aj)(ai,aj)有多少对? 分析: 题目n范围是 1~1E6,不能用o(n2)o(n2)方法暴力搞 使用筛法,把每个数字的倍数都筛选一遍,然后每个数字都可以知道前面有多少个自己的约数,从1~maxai扫一遍,计算相应的组合数 还有自己和自己组合的情况 遇到的问题: 每个数字可能出现多次, 更新约数个

每日站立会议——20160423

每日站立会议——20160423 一.站立会议信息       早起后经讨论,小组成员决定了今天将要进行的工作任务.总结了昨天进行的工作及遇到的困难,并对未完成的工作进行了分析. 小组“站立会议”,有图有真相: 二.任务进度 我们依旧继续搭界面.改播放界面.编写暂停音乐和计时功能,虽然效率真心有点低,但是我们坚信我们一定可以完成第一阶段的冲刺.同样我们不会停止自己看书学习基本安卓知识的脚步……^O^ 三.任务看板图 四.燃尽图

[2016-04-17][Gym][100947][F][black-white]

时间:2016-04-17 17:06:43 星期日 题目编号:[2016-04-17][Gym][100947][F][black-white] 题目大意:在一行格子中,有一个白棋和一个黑旗,每次移动一个,给出一个状态,白棋先移动,问最后胜利的人是水 分析: 只要白棋和黑棋始终保持奇数的间隔(即轮到白棋走的时候,黑白间隔奇数个),最后黑棋一定会被逼到角落,然后间隔不断减小(减小之和还是奇数间隔),最后黑棋败 #include<cstdio> using namespace std; int

[2016-04-17][Gym][100947][D][The Three Kings of Asgard]

时间:2016-04-17 16:45:30 星期日 题目编号:[2016-04-17][Gym][100947][D][The Three Kings of Asgard] 题目大意:A给B和当前一样多的金币,B给C,然后C又给A,结束之后,A,B,C三人的金币刚好一样多,问原来A,B,C各有多少个金币,不可能就输出 Impossible 分析: 直接解方程组 ?????2×(a?b)=n2×b?c=n2c?(a?b)=n{2×(a?b)=n2×b?c=n2c?(a?b)=n 得到 ?????

[2016-04-17][Gym][100947][B][Queens, Again!!]

时间:2016-04-17 16:20:49 星期日 题目编号:[2016-04-17][Gym][100947][B][Queens, Again!!] 题目大意:8皇后问题,给出8皇后的位置,判断8皇后是否能互相攻击 分析: 同行,同列,同对角线 同对角线:横纵坐标之差,之和相同 遇到的问题: #include<cstdio> using namespace std; struct Point{ int x,y; }p[10]; int check(int a,int b){ if(p[a

[2016-04-17][Gym][100947][C][Rotate It !!]

时间:2016-04-17 16:35:01 星期日 题目编号:[2016-04-17][Gym][100947][C][Rotate It !!] 题目大意:给定一列数字,从第一个开始取,每隔一个数字取一个数字,有一个操作就是把第一个数字放在最后,可以无限次操作,问最大的取值是多少 分析: 可以看成一个环,每个环,可以从每个环开始取,问最大的取值是多少 数字是偶数个,很简单,直接就是求奇数位置和偶数位置之和的最大值 数字是奇数个, 分析可以知道,一定有相邻的两个数字在选中的序列中,那么只需要枚

[2016-04-17][Gym][100947][A][Traffic Lights]

时间:2016-04-17 16:16:03 星期日 题目编号:[2016-04-17][Gym][100947][A][Traffic Lights] 题目大意:给出红黄绿灯的时间,刚刚转到绿灯,给出当时到达路口的时间,问到达路口的时候,灯的状态 分析:直接计算即可 #include<cstdio> using namespace std; int main(){ int x,g,y,r,t; scanf("%d",&t); while(t--){ scanf(&

20160423/24省赛选拔总结

最近一直在重温c语言,没有时间总结比赛,眼看还有一年就要准备实习了,大部分精力都放在为找工作做准备的阶段,没有太多精力刷题,能做的只是总结每一场训练赛中的失误与不足 省赛选拔虽然选上了,但还是很不顺利,,,,,,,,,,,我和小王去年国赛因为题意的问题错失了一枚铜牌,这次再次因为题意翻译出了问题卡了一场比赛:: 第一天:::刚发下来,我们3个人还算很准确,分别翻译A,B,C, 我先把B题翻译出来了,明确了思路,我直接上去敲B题,一遍AC过,我昨晚,学长翻译完了A题,并且有了思路,确定了用状压DP