题目为CSU 1328--1339
总结
不是我语死早就是出题人语死早
A
B
直接用链表就行,当时还傻乎乎的用线段树去做。
赛后打算用链表做时敲到一半突然发现。。。。链表已经忘得一干二净。。。。。。。。敲了半天
注意建立链表时头尾的处理,最好留空表头和表尾。
还有X,Y是指盒子的值不是盒子的位置。
-------------------------------------------------------------------------------------我是去你妹的分割线---------------------------------------------------------------------------------------
敲你妹的链表啊,好不容易敲完发现超时了,果然什么链表都去死才适合我,直接用两个个数组就就搞定了,才260ms有木有,算了,就当复习下链表
注意衔接细节就行了,像我一样神经大条的画个图把前驱后继都标上就不会漏了,还有就是x,y相邻时要注意处理
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int MAX=1111111;
int n,m;
bool flag;
long long sum;
int l[MAX];
int r[MAX];
int main()
{
int ca=1;
int i,j;
int op;
int x,y;
int temp;
int a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<=n+1;++i) //防止越界
{
l[i]=i-1;
r[i]=i+1;
}
flag=true;
while(m--)
{
scanf("%d",&op);
if(op==4)
{
flag=!flag;
}
else
{
scanf("%d%d",&a,&b);
if(op==3)
{
if(l[a]==b) //x,y相邻,特殊处理 //注意交换后,原来前驱的后继也要变,后继的前驱也是
{
r[b]=r[a];
l[a]=l[b];
r[l[b]]=a;
l[b]=a;
l[r[a]]=b;
r[a]=b;
}
else if(r[a]==b)
{
r[a]=r[b];
l[b]=l[a];
r[l[a]]=b;
l[a]=b;
l[r[b]]=a;
r[b]=a;
}
else
{
r[l[a]]=b;
l[r[a]]=b;
r[l[b]]=a;
l[r[b]]=a;
temp=l[a];
l[a]=l[b];
l[b]=temp;
temp=r[a];
r[a]=r[b];
r[b]=temp;
}
}
else if((op==1&&flag)||(op==2&&!flag)) //判断条件要设置对
{
r[l[a]]=r[a];
l[r[a]]=l[a];
l[a]=l[b];
r[a]=b;
r[l[b]]=a;
l[b]=a;
}
else
{
r[l[a]]=r[a];
l[r[a]]=l[a];
r[a]=r[b];
l[a]=b;
l[r[b]]=a;
r[b]=a;
}
}
}
sum=0;
if(flag)
{
temp=r[0];
for(i=1;i<=n;)
{
sum+=temp;
temp=r[r[temp]];
i+=2;
}
}
else
{
temp=l[n+1];
for(i=1;i<=n;)
{
sum+=temp;
temp=l[l[temp]];
i+=2;
}
}
printf("Case %d: %lld\n",ca++,sum);
}
return 0;
}
C
尼玛,这代号也太抽象了吧,百思不得其解题意,结果突然看到长得和1.2.3一样。。。。。。就理解题意了
就是靠第四行的*位置来判断是1还是2还是3。读懂题意后就想去撞墙了。。。
D
E
F
G
H
很明显是线段树,结果前面几道卡了太多时间(再一次撞墙),来不及做
一开始想到为设最大高度的线段树,然后发现要各种离散化,看别人a得很快,所以就觉得不可能是这样做的。
赛后做时就立马想到解题思路了。。。。
先把每座桥的高度从小到大排序,然后设n的线段树,底部叶子节点保存的信息为每座桥被淹没的次数,其他节点为延迟标记,然后每次更新时对被覆盖的区间成段更新(用对应位置的桥高度进行二分比较查找),具体代码如下
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=int(1e8)+11;
const int M=int(1e5)+11;
#define ls l,mid,root<<1
#define rs mid+1,r,root<<1|1
int n,m,k;
int line[M<<3];
int arr[M];
int num;
int sum;
bool cmp(int x,int y)
{
return x<y;
}
void build(int l,int r,int root)
{
if(l==r)
{
line[root]=0;
return ;
}
int mid=(l+r)>>1;
build(ls);
build(rs);
line[root]=0;
}
void pushdown(int root)
{
if(line[root]!=0)
{
line[root<<1]+=line[root];
line[root<<1|1]+=line[root];
line[root]=0;
}
}
void update(int l,int r,int root,int low,int hig)
{
if(low<=arr[l]&&hig>=arr[r])
{
line[root]++;
return;
}
if(l==r)
{
return;<span style="white-space:pre"> </span>//注意递归出口的设置,会出现比最低的桥值低,比最高的桥值高的情况,在这里re了好几发。。。。。
}
pushdown(root);
int mid=(l+r)>>1;
if(low<=arr[mid])
{update(ls,low,hig);}
if(hig>arr[mid])
{update(rs,low,hig);}
}
void query(int l,int r,int root,int p)
{
if(l==r)
{
if(line[root]>=k)
{sum++;}
return;
}
pushdown(root);
int mid=(l+r)>>1;
if(p<=mid)
{query(ls,p);}
else
{query(rs,p);}
}
int main()
{
int ca=1;
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
int i,j;
int hig,low;
int last=1;;
for(i=1;i<=n;++i)
{scanf("%d",&arr[i]);}
sort(arr+1,arr+n+1,cmp);<span style="white-space:pre"> </span>//sort排序时注意数组开头的结束位置,在这里wa了一发。。。果然是弱得一B
num=1;
build(1,n,1);
while(m--)
{
scanf("%d%d",&hig,&low);
update(1,n,1,last+1,hig);
last=low;
}
sum=0;
for(i=1;i<=n;++i)
{
query(1,n,1,i);
}
printf("Case %d: %d\n",ca++,sum);
}
return 0;
}
/*
1 2 1
5
6 2
3 1
*/
此外还有一种简单的做法,直接开一个数组标记下淹没的起始和结束位置,然后扫一遍就行,和之前在bestcode做过的一道题一样
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX=int(1e8)+11;
const int M=int(1e5)+11;
int n,m,k;
int arr[M];
int status[M];
bool cmp(int x,int y)
{
return x<y;
}
int find(int l,int r,int v)
{
if(v==1)
{return 0;} //初始水位为1,往前-1;
if(l==r)
{
return l;
}
int mid=(l+r)>>1;
if(v<=arr[mid])
{find(l,mid,v);}
else
{find(mid+1,r,v);}
}
int main()
{
int ca=1;
int i,j;
int a,b;
int last;
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
for(i=1;i<=n;++i)
{scanf("%d",&arr[i]);}
sort(arr+1,arr+1+n,cmp);
last=1;
memset(status,0,sizeof(status));
while(m--)
{
scanf("%d%d",&a,&b);
status[find(1,n,last)+1]++; //上次退潮高度已经被淹没,往后+1
status[find(1,n,a)+1]--; //即使处于涨潮高度仍被淹没,往后+1
last=b;
}
int sum=0;
int temp=0;
for(i=1;i<=n;++i)
{
printf("status[%d]=%d\n",i,status[i]);
temp+=status[i];
if(temp>=k)
{sum++;}
}
printf("Case %d: %d\n",ca++,sum);
}
return 0;
}
I
J
其实很简单,就是一开始不敢去尝试,还好之前有看过枚举的优化,枚举A,B就行了,把计算得到的C进行验证,还有一个是剪枝,A,B的最大值只能是1000,优化一下就行了,100msAC后在自喜,看到别人居然是4ms。。。。。我还是太弱了。。。。
K
L
尼玛,题意没看清,数组开小了,结果就一直wa了3发!掩面而泣~po主去蹲角落了~~