noip9

T1

本次考试最水的一道题,然而我sb,前一个小时,找了一大堆跟题目无关的性质,干脆打了个20pts的表,然后就走了,最后几分钟才看出来,匆匆码出来,结果段错误,然后考试就结束了。
好吧,段错误是UB,返回值的原因,%%%TLEer,加个return就好了。
就是找规律,\(fa_{now}=now-f_{i}\) ,其中 \(f_{i} < now\le f_{i+1}\) 即第一个比 \(now\) 小的斐波那契数,然后就没啥了,记得开long long。

Code
#include<cstdio>
#include<algorithm>
#define re register
#define int long long
namespace OMA
{
   int m;
   int f[65]={0,1,1};
   inline int read()
   {
     int s=0,w=1; char ch=getchar();
     while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
     while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
     return s*w;
   }
   int LCA(int a,int b)
   {
     if(a==1||b==1)
     { return 1; }
     if(a==b)
     { return a; }
     int temp1 = std::lower_bound(f+1,f+61,a)-f-1;
     int temp2 = std::lower_bound(f+1,f+61,b)-f-1;
     while(a-f[temp1]>=b)
     { a -= f[temp1],temp1 = std::lower_bound(f+1,f+temp1,a)-f-1; }
     while(b-f[temp2]>=a)
     { b -= f[temp2],temp2 = std::lower_bound(f+1,f+temp2,b)-f-1; }
     if(a==1||b==1)
     { return 1; }
     if(a==b)
     { return a; }
     return LCA(a-f[temp1],b-f[temp2]);
   }
   signed main()
   {
     f[0]=0;
     m = read();
     for(re int i=3; i<=60; i++)
     { f[i] = f[i-1]+f[i-2]; }
     for(re int i=1; i<=m; i++)
     { int a=read(),b = read(); printf("%lld\n",LCA(a,b)); }
     return 0;
   }
}
signed main()
{ return OMA::main(); }

T2

暴力拿了30pts,后来时限开大,拿了60pts。
正解很多,这里是二分。
首先按照颜色和位置排序,然后考虑题目中的两个操作。
第一个询问操作,只需要对排序后的数组二分查找,下标差即是答案。
第二个修改操作,因为修改并不会改变同种颜色的相对顺序,所以只需要找到位置并进行修改就好了。
其实也是挺水的
线段树做法

Code
#include<cstdio>
#include<algorithm>
#define MAX 300001
#define re register
namespace OMA
{
   int n,m;
   int a[MAX];
   struct node
   {
     int c;
     int pos;
     friend bool operator <(const node &x,const node &y)
     { return (x.c!=y.c)?x.c<y.c:x.pos<y.pos; }
   }col[MAX];
   inline int read()
   {
     int s=0,w=1; char ch=getchar();
     while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
     while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
     return s*w;
   }
   inline void swap(int &a,int &b)
   { int t=a; a=b; b=t; }
   signed main()
   {
     n = read(),m = read();
     for(re int i=1; i<=n; i++)
     { a[i] = col[col[i].pos = i].c = read(); }
     std::sort(col+1,col+1+n);
     for(re int i=1; i<=m; i++)
     {
       int opt = read();
       if(opt==1)
       {
         int l = read(),r = read(),c = read();
         int L = std::lower_bound(col+1,col+1+n,node{c,l})-col;
         int R = std::upper_bound(col+1,col+1+n,node{c,r})-col-1;
         printf("%d\n",R-L+1);
       }
       if(opt==2)
       {
         int x = read();
         if(a[x]==a[x+1])
         { continue; }
         col[std::lower_bound(col+1,col+1+n,node{a[x],x})-col].pos = x+1;
         col[std::lower_bound(col+1,col+1+n,node{a[x+1],x+1})-col].pos = x;
         swap(a[x],a[x+1]);
       }
     }
     return 0;
   }
}
signed main()
{ return OMA::main(); }

upd on 2021-08-22

模拟题里有道回滚莫队,然而我分块都不太会,所以学了学,发现这道题可以拿分块硬草过去。

如果直接按 \(\sqrt{n}\) 来分,会 \(MLE\) ,然后,我选的是200MIB来卡,经过一波计算,发现块长应为1740左右,大概是 \(n^{\frac{19}{32}}\),这样就分出了大概170个块,不会MLE,内存200MIB左右,最劣复杂度 \(O(m(\frac{n}{T}+T))\),其中 \(T\) 为块的大小 \(n^{\frac{19}{32}}\),luogu跑了5.1s,最慢的点855ms。还是慎用吧

bb那么多,其实直接用个short就行,made

然而oj慢的很,95pts卡不过去,卡不动了。虽然有人过了

Code
#include<cmath>
#include<cstdio>
#define MAX 300010
#define re register
const int LEN = 220;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			int w=1; s=0; char ch=getchar();
			while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
			while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
			return s*=w,*this;
		}
	}cin;
	inline void write(int x)
	{
		int sta[35],top = 0;
		do
		{
			sta[++top] = x-(x/10)*10;
			x /= 10;
		}while(x);
		while(top)
		{ putchar(sta[top--]+'0'); }
		putchar('\n');
	}
}using namespace some;
namespace OMA
{
	int n,m,len;
	int col[MAX];
	short id[MAX],sum[LEN][MAX];
	struct BLOCK
	{
		/*inline void update(int p1,int p2)
		{
			sum[id[p1]][col[p1]]--;
			sum[id[p1]][col[p2]]++;
			sum[id[p2]][col[p1]]++;
			sum[id[p2]][col[p2]]--;
			int t = col[p1];
			col[p1] = col[p2]; col[p2] = t;
		}*/
		inline int query(int l,int r,int c)
		{
			int res = 0;
			int p1 = id[l],p2 = id[r];
			if(p1==p2)
			{
				for(re int i=l; i<=r; i++)
				{
					if(col[i]==c)
					{ res++; }
				}
				return res;
			}
			for(re int i=l; id[i]==p1; i++)
			{
				if(col[i]==c)
				{ res++; }
			}
			for(re int i=p1+1; i<=p2-1; i++)
			{ res += sum[i][c]; }
			for(re int i=r; id[i]==p2; i--)
			{
				if(col[i]==c)
				{ res++; }
			}
			return res;
		}
	}block;
	signed main()
	{
		cin >> n >> m; len = pow(n,5.0/8.0);
		for(re int i=1; i<=n; i++)
		{
			cin >> col[i];
			id[i] = (i-1)/len+1;
			sum[id[i]][col[i]]++;
		}
		for(re int i=1,opt,l,r,c,x; i<=m; i++)
		{
			cin >> opt;
			if(opt==1)
			{
				//int l,r,c;
				cin >> l >> r >> c;
				//printf("%d\n",block.query(l,r,c));
				write(block.query(l,r,c));
			}
			if(opt==2)
			{
				//int x;
				cin >> x;
				if(x==n)
				{ continue ; }
				//block.update(x,x+1);
				int p1 = x,p2 = x+1;
				sum[id[p1]][col[p1]]--;
				sum[id[p1]][col[p2]]++;
				sum[id[p2]][col[p1]]++;
				sum[id[p2]][col[p2]]--;
				int t = col[p1];
				col[p1] = col[p2]; col[p2] = t;
			}
		}
		return 0;
	}
}
signed main()
{ return OMA::main(); }

T3

没改出来

posted @ 2021-06-22 20:33  -OMA-  阅读(95)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end