留坑....

改完题再说吧。

留坑....

最近考得什么鬼??
模拟53
T1 u(差分)


一道差分题????
然而考场没有想到如何维护斜率上的差分,事后经miemeng和cyf的生(xuan)动(xue)讲解大概是懂了
联想如何维护一个矩形的差分??
假设我们区间修改为L1,R1,L2,R2,
我们在L2+1,R2+1处+1,在L1,R1处+1,在L2+1,R1处-1,在L1,R2+1处-1,然后画图发现从左向右递推时
我们维护的二维前缀和中有+1的部分恰好是区间修改的部分
同理,我们现在维护出一个三角形
首先考虑斜率,假设L1,R1左上角,len为直角边长度,在L1,R1加一,在L1+len,R1+len处-1我们按斜率递推一下就得到斜线上的贡献,然后在考虑直线上的贡献,我们在维护列上的前缀和,然后再按行递推一下就可以画出三角形

 1 #include<bits/stdc++.h>
2 #define MAXN 2101
3 #define int long long
4 using namespace std;
5 int hang[MAXN][MAXN];int lie[MAXN][MAXN];int sum[MAXN][MAXN];
6 int n,q;
7 int read(){
8 int x=0;char c=getchar();
9 while(c<'0'||c>'9')c=getchar();
10 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
11 return x;
12 }
13 int ans=0;
14 signed main(){
15 n=read();q=read();
16 for(int i=1;i<=q;++i){
17 int l=read();int r=read();int len=read();int s=read();
18 lie[l][r-1]-=s;
19 lie[l+len][r-1]+=s;
20 sum[l][r]+=s;
21 sum[l+len][r+len]-=s;
22 }
23 for(int i=1;i<=2*n;++i){
24 for(int j=1;j<=2*n;++j){
25 sum[i][j]=sum[i][j]+sum[i-1][j-1];
26 }
27 }
28 for(int j=1;j<=2*n;++j){
29 for(int i=1;i<=2*n;++i){
30 lie[i][j]=lie[i][j]+lie[i-1][j];
31 }
32 }
33 for(int j=2*n;j>=1;--j){
34 for(int i=1;i<=n*2;++i){
35 hang[i][j]=sum[i][j]+lie[i][j];
36 hang[i][j]+=hang[i][j+1];
37 }
38 }
39 for(int i=1;i<=n;++i){
40 for(int j=1;j<=n;++j)
41 ans^=hang[i][j];
42 }
43 printf("%lld\n",ans);
44 }


T2 v(哈希表,记忆化搜索)


第一学了哈系表,因为当前决策不明,而且n的范围很小,所以就记忆化搜索了????

 1 #include<bits/stdc++.h>
2 #define MAXN 31000001
3 #define int long long
4 using namespace std;
5 int read(){
6 int x=0;char c=getchar();
7 while(c<'0'||c>'9')c=getchar();
8 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
9 return x;
10 }
11 int k;int n;
12 const int mod=30000001;
13 struct map_hash{
14 struct node{int to,n;double val;int len;}e[31000001];
15 int tot=0;
16 int head[MAXN];int len=0;
17 double &operator[](int state){
18 int st=state*len%mod+1;
19 for(int i=head[st];i;i=e[i].n){
20 if(e[i].to==state&&e[i].len==len)
21 return e[i].val;
22 }
23 e[++tot].to=state;
24 e[tot].val=-1.0;
25 e[tot].len=len;
26 e[tot].n=head[st];
27 head[st]=tot;
28 return e[tot].val;
29 }
30 }f;
31 int base[MAXN];
32 int getnum(int state,int k){
33 if(k==0)return (state>>1);
34 int kx=(state>>(k+1));
35 return (kx<<(k))|(state&base[k-1]);
36 }
37 double DFS(int state,int len){
38 if(len==n-k)return 0;
39 f.len=len;
40 if(f[state]!=-1.0)return f[state];
41 double sum=0;
42 for(int i=1;i<=len/2;++i){
43 int ok1=(state>>(i-1))&1;
44 int find1=getnum(state,i-1);
45 int ok2=(state>>(len-i))&1;
46 int find2=getnum(state,len-i);
47 sum+=2*max(DFS(find1,len-1)+ok1,DFS(find2,len-1)+ok2);
48 }
49 if(len&1){
50 int kx=len/2+1;
51 int ok1=(state>>(kx-1))&1;
52 int find1=getnum(state,kx-1);
53 sum+=DFS(find1,len-1)+ok1;
54 }
55 sum=sum/len;
56 f.len=len;
57 return f[state]=sum;
58 }
59 int st=0;
60 signed main(){
61 n=read();k=read();
62 base[0]=1;
63 for(int i=1;i<=n;++i)base[i]=base[i-1]|(1<<i);
64 for(int i=1;i<=n;++i){
65 char x=getchar();
66 if(x=='W')st|=1<<(i-1);
67 }
68 double ans=DFS(st,n);
69 printf("%.7lf\n",ans);
70 }

T3 w(神仙DP)


第一次作二元组DP很神仙。

性质:1.遇到需要反的边一定要反,遇到不能反的边一定不能反

2.任何操作数其实等于树中翻过的奇数点数/2

所以DP[1/0].fir表示是当前节点是/否向上反边时的计数点个数,sec表示最小路径长度

所以转移时w1,w0分别表示子树贡献,定义同上

转载校外大佬博客(实际是因为自己懒得写了QAQ)

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define min(a,b) (a)<(b)?(a):(b)
4 #define inf 0x7ffffff
5 #define MAXN 1000000
6 #define int long long
7 int read(){
8 int x=0;char c=getchar();
9 while(c<'0'||c>'9')c=getchar();
10 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
11 return x;
12 }
13 struct node{
14 int fir;int sec;
15 friend node operator +(node a,node b){
16 return (node){a.fir+b.fir,a.sec+b.sec};
17 }
18 };
19 inline node minn(node a,node b){
20 if(a.fir==b.fir)return a.sec<b.sec?a:b;
21 return a.fir<b.fir?a:b;
22 }
23 struct no{
24 int n,to,w;
25 }e[MAXN];
26 int n;
27 int head[MAXN],tot;
28 void add(int u,int v,int w){
29 e[++tot].n=head[u];e[tot].to=v;e[tot].w=w;head[u]=tot;
30 }
31 node dp[MAXN][2];int fa[MAXN];
32 void DP(int x,int faa){
33 node w0=(node){0,0},w1=(node){inf,inf};
34 node t0=(node){0,0},t1=(node){inf,inf};
35 for(int i=head[x];i;i=e[i].n){
36 int to=e[i].to;
37 if(to==faa)continue;
38 DP(to,x);
39 t0=w0,t1=w1;
40 w0=minn(t0+dp[to][0],t1+dp[to][1]);
41 w1=minn(t0+dp[to][1],t1+dp[to][0]);
42 }
43 dp[x][0]=minn((node){w0.fir,w0.sec},(node){w1.fir+1,w1.sec});
44 dp[x][1]=minn((node){w0.fir+1,w0.sec+1},(node){w1.fir,w1.sec+1});
45 if(fa[x]==0){
46 dp[x][1]=(node){inf,inf};
47 }
48 else if(fa[x]==1){
49 dp[x][0]=(node){inf,inf};
50 }
51 }
52 void DFS(int x,int faa){
53 for(int i=head[x];i;i=e[i].n){
54 int to=e[i].to;
55 if(to==faa)continue;
56 int w=e[i].w;
57 fa[to]=w;
58 DFS(to,x);
59 }
60 }
61 signed main(){
62 n=read();
63 for(int i=1;i<=n-1;++i){
64 int u,v,a,b;
65 u=read();v=read();a=read();b=read();
66 if(b!=2){add(u,v,a^b);add(v,u,a^b);}
67 else add(u,v,b),add(v,u,b);
68 }
69 DFS(1,0);
70 DP(1,0);
71 printf("%lld %lld\n",dp[1][0].fir/2,dp[1][0].sec);
72 }

模拟52

T1平均数(归并排序+二分)


发现自己一个小时没有思路,放弃........

一直以为是神仙数据结构.....

其实只要二分平均值后将所有值减去该值,查找和<0的区间个数,

怎么求,归并排序就好了.....

 1 #include<bits/stdc++.h>
2 #define MAXN 101000
3 #define int long long
4 #define inf 0.00001
5 using namespace std;
6 double sum[MAXN],kx[MAXN];double zzn[MAXN];double maxn;
7 int read(){
8 int x=0;char c=getchar();
9 while(c<'0'||c>'9')c=getchar();
10 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
11 return x;
12 }
13 int anss=0;int n;int a[MAXN];int k;
14 void guibing(int l,int r){
15 if(l==r){kx[l]=sum[l];return ;}
16 int mid=(l+r)>>1;
17 guibing(l,mid);guibing(mid+1,r);
18 int le=l;int re=mid+1;int mm=0;
19 while(le<=mid&&re<=r){
20 if(kx[re]<kx[le]){zzn[++mm]=kx[le];le++;}
21 else{
22 zzn[++mm]=kx[re];
23 anss+=(le-l);
24 re++;
25 }
26 }
27 while(le<=mid){
28 zzn[++mm]=kx[le];le++;
29 }
30 while(re<=r){
31 zzn[++mm]=kx[re];anss+=(le-l);
32 re++;
33 }
34 for(int i=l;i<=r;++i){
35 kx[i]=zzn[i-l+1];
36 }
37 }
38 int work(double len){
39 anss=0;
40 for(int i=1;i<=n;++i){
41 sum[i]=sum[i-1]+((double)a[i]-len);
42 if(sum[i]<0)anss++;
43 kx[i]=0.0;
44 }
45 guibing(1,n);
46 return anss;
47 }
48 void second_divied(){
49 double l=0;double r=maxn;
50 while(l+inf<r){
51 double mid=(l+r)/2.000;
52 if(work(mid)<k)l=mid;
53 else r=mid;
54 }
55 if(work(l)==k)printf("%.4lf\n",l);
56 else printf("%.4lf\n",r);
57 }
58 signed main(){
59 n=read();k=read();
60 for(int i=1;i<=n;++i)a[i]=read(),maxn=max(maxn,(double)a[i]);
61 second_divied();
62 }

***********************

思路积累:

1.求排名第k小转化为有k个比他小的序列

2.平均数可以二分后,让所有数减去该值。

T2涂色游戏(组合数学)


考场死刚.....

最后式子推的基本对了,但是还是有点问题,快速幂打错怒丢30!!!

首先要处理好j,k两列颜色种类有x个颜色交集时的方案数

还要与处理出在n行放k种颜色的方案数

然后转移时发现对于该列有j种颜色,我们先乘f[n][j]/C(p,j)表明我们并不知道所放颜色的具体颜色,只知道一个排列顺序,

对于每一个上一列的状态我们可以转移到该列,

然后乘上相应组合数求出上一列颜色固定时下一列的颜色种类的方案,再乘上排列方式即可

  1 #include<bits/stdc++.h>
2 #define int long long
3 #define MAXN 1100
4 using namespace std;
5 int read(){
6 int x=0;char c=getchar();
7 while(c<'0'||c>'9')c=getchar();
8 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
9 return x;
10 }
11 int n,m,p,q;
12 int dp[MAXN][MAXN];
13 int jie[MAXN],ni[MAXN],ni_c[MAXN];
14 const int mod=998244353ll;
15 int C(int x,int y){
16 if(y>x)return 0;
17 if(y==0)return 1;
18 return jie[x]*ni_c[y]%mod*ni_c[x-y]%mod;
19 }
20 int poww(int x,int y){
21 int ans=1ll;
22 while(y){
23 if(y&1)ans=(ans*x)%mod;
24 x=(x*x)%mod;
25 y>>=1;
26 }
27 return ans%mod;
28 }
29 int ans=0;int kx[MAXN][MAXN];
30 int fir[MAXN][MAXN];int f[2][MAXN];int c[MAXN][MAXN];
31 void work1(){
32 memset(c,0,sizeof(c));
33 for(int k=1;k<=min(n,p);++k){
34 for(int i=1;i<=min(n,p);++i){
35 for(int j=1;j<=min(n,p);++j){
36 c[i][j]=(c[i][j]+fir[i][k]*kx[k][j]%mod)%mod;
37 }
38 }
39 }
40 for(int i=1;i<=min(n,p);++i){
41 for(int j=1;j<=min(n,p);++j)
42 fir[i][j]=c[i][j]%mod;
43 }
44 }
45 void work2(){
46 memset(c,0,sizeof(c));
47 for(int k=1;k<=min(n,p);++k){
48 for(int i=1;i<=min(n,p);++i){
49 for(int j=1;j<=min(n,p);++j){
50 c[i][j]=(c[i][j]+kx[i][k]*kx[k][j]%mod)%mod;
51 }
52 }
53 }
54 for(int i=1;i<=min(n,p);++i){
55 for(int j=1;j<=min(n,p);++j)
56 kx[i][j]=c[i][j];
57 }
58 }
59 void ju_poww(int y){
60 for(int i=1;i<=min(n,p);++i)fir[i][i]=1;
61 while(y){
62 if(y&1){work1();}
63 work2();
64 y>>=1;
65 }
66 }
67 signed main(){
68 n=read();m=read();p=read();q=read();
69 dp[0][0]=1;
70 for(int i=1;i<=n;++i){
71 for(int j=1;j<=min(p,i);++j){
72 dp[i][j]=(dp[i-1][j-1]*(p-(j-1)+mod)%mod+dp[i-1][j]*j%mod)%mod;
73 }
74 }
75 jie[0]=jie[1]=1;ni[1]=1;ni_c[0]=ni_c[1]=1;
76 for(int i=2;i<=p;++i){
77 jie[i]=(jie[i-1]*i)%mod;
78 ni[i]=((mod-mod/i)*ni[mod%i])%mod;
79 ni_c[i]=(ni[i]*ni_c[i-1])%mod;
80 }
81 for(int j=1;j<=p;++j){
82 f[0][j]=dp[n][j]%mod;
83 }
84 for(int j=1;j<=min(n,p);++j){
85 for(int k=1;k<=min(n,p);++k){
86 if(j+k<q)continue;
87 for(int x=max(j,max(q,k));x<=min(p,j+k);++x){
88 kx[j][k]=(kx[j][k]+C(p-j,x-j)%mod*C(j,k+j-x)%mod)%mod;
89 }
90 kx[j][k]%=mod;
91 kx[j][k]=kx[j][k]*poww(C(p,k)%mod,mod-2)%mod*dp[n][k]%mod;
92 kx[j][k]%=mod;
93 }
94 }
95 ju_poww(m-1);
96 for(int j=1;j<=p;++j){
97 for(int k=1;k<=p;++k){
98 f[1][j]=(f[1][j]+f[0][k]*fir[k][j]%mod)%mod;
99 }
100 }
101 int ans=0;
102 for(int j=1;j<=p;++j)ans=(ans+f[1][j])%mod;
103 printf("%lld\n",ans);
104 }

T3序列(数据结构乱搞)


好像是这套题里最简单的......

直接在树状数组里开vector每次查询时就lowerbound查出贡献

对于查询覆盖了一段区间的查询,我们在L,R+1处用两个树状数组标记后缀

然后对于询问覆盖x位置的值就用L的(1-x)的L贡献-(1-x)的R的贡献

 1 #include<bits/stdc++.h>
2 #define MAXN 410000
3 #define int long long
4 using namespace std;
5 vector<int>v[MAXN];vector<int>v1[MAXN];
6 int lowbit(int x){return x&(-x);}
7 int m,q,n,a[MAXN];
8 void add(int x,int k){
9 for(int i=x;i>=1;i-=lowbit(i)){
10 v[i].push_back(k);//printf("ps=%lld i=%lld\n",i,k);
11 }
12 }
13 void add1(int x,int k){
14 for(int i=x;i>=1;i-=lowbit(i)){
15 v1[i].push_back(k);//printf("ps=%lld i=%lld\n",i,k);
16 }
17 }
18 int anss[MAXN];
19 void pt(int x){
20 for(int i=0;i<v[x].size();++i){
21 printf("%lld ",v[x][i]);
22 }cout<<endl;
23 }
24 int query(int x,int k){
25 int ans=0;
26 for(int i=x;i<=n+1;i+=lowbit(i)){
27 int kx=upper_bound(v[i].begin(),v[i].end(),k)-v[i].begin()-1;
28 ans+=kx;
29 }
30 return ans;
31 }
32 int query1(int x,int k){
33 int ans=0;
34 for(int i=x;i<=n+1;i+=lowbit(i)){
35 int kx=upper_bound(v1[i].begin(),v1[i].end(),k)-v1[i].begin()-1;
36 ans+=kx;
37 }
38 return ans;
39 }
40 int read(){
41 int x=0;char c=getchar();
42 while(c<'0'||c>'9')c=getchar();
43 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
44 return x;
45 }
46 int sum=0;
47 signed main(){
48 n=read();m=read();q=read();
49 for(int i=1;i<=n+1;++i){v[i].push_back(0);v[i].push_back(0x7fffffffffff);v1[i].push_back(0);v1[i].push_back(0x7fffffffffff);}
50 for(int i=1;i<=n;++i){
51 a[i]=read();
52 }
53 for(int i=1;i<=m;++i){
54 int l=read();int r=read();int xx=read();
55 add(l,xx);
56 add1(r+1,xx);
57 }
58 for(int i=1;i<=n+1;++i)sort(v[i].begin(),v[i].end()),sort(v1[i].begin(),v1[i].end());
59 for(int i=1;i<=n;++i){
60 anss[i]=(query(1,a[i])-query(i+1,a[i]));
61 anss[i]-=(query1(1,a[i])-query1(i+1,a[i]));
62 sum+=anss[i];
63 }
64 printf("%lld\n",sum);
65 for(int i=1;i<=q;++i){
66 int u=read();int v=read();
67 u^=sum;v^=sum;
68 sum-=anss[u];
69 anss[u]=query(1,v)-query(u+1,v);
70 anss[u]-=(query1(1,v)-query1(u+1,v));
71 sum+=anss[u];
72 a[u]=v;
73 printf("%lld\n",sum);
74 }
75 }
76 /*
77 4 2 2
78 1 4 2 3
79 2 4 3
80 1 3 2
81 6 6
82 2 7
83 */

最新文章

  1. 邻接表的广度优先遍历(java版)
  2. [LeetCode] Power of Four 判断4的次方数
  3. 耿丹CS16-2班第三次作业汇总
  4. 关于.9.png格式图片的制作与使用
  5. MySql数据库忘记root密码
  6. 什么时候该用NoSQL?
  7. salesforce 零基础开发入门学习(五)异步进程介绍与数据批处理Batchable
  8. CentOS配置本地yum源(使用镜像iso文件)
  9. struts2在web.xml中的配置
  10. Android Focusable in Touch Mode 介绍
  11. 推荐一个CodeProject上的SlideForm控件
  12. iOS常见面试题汇总
  13. 【poj1087/uva753】A Plug for UNIX(最大流)
  14. asp.net2.0安全性(1)--用户角色篇(类)--转载来自车老师
  15. [C#、winform] FormDesigner.cs报错The variable &#39;xxxxxx&#39; is either undeclared or was never assigned
  16. ubuntu apache2 流量限制模块
  17. seaborn使用(样式管理)
  18. 爸爸又给Spring MVC生了个弟弟叫Spring WebFlux
  19. 高校表白APP-冲刺第二天
  20. Java如何检查文件是否在服务器上被修改了?

热门文章

  1. Kafka源码分析(一) - 概述
  2. Redis数据结构—跳跃表
  3. HEVC学习(一) —— HM的使用
  4. FROM-4-TO-6!!!!!!!!! - OO第二单元总结
  5. 19 常用API
  6. Markdown使用概述
  7. [DB] Spark Core (1)
  8. 使用 IPMI 远程为服务器安装操作系统教程
  9. IDEA 安装 zookeeper 可视化管理插件
  10. 004.kubernets对于pod的简单管理