標籤:dea mat end ios sort tor bzoj int name
有N個位置,M個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入一個數c
如果是2 a b c形式,表示詢問從第a個位置到第b個位置,第C大的數是多少。
為了強制線上,每一次的a,b是加密的,需要異或lastans的後8位進行解密,其中lastans為上次輸出的結果,初始為零。
如果解密後a>b則先交換a,b
資料保證解密後a,b不會超過N
如果解密後a,b出現0,則賦值為1。
來曆:bzoj上的一道題,經過子禎學長的魔改後,資料範圍變得很奇怪...
演算法:樹套樹;
權值線段樹套線段樹;
套線段樹有技巧:一顆線段樹可以先只創造一個點,其他需要的節點需要用到的時候再開就可以了;
其他的也沒什麼可說了,看代碼吧:
(不要交到bzoj上,過不了,這是經過魔改的題目)
(不建議借鑒,初次寫這種題,code還比較稚嫩)
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<set>#include<map>#include<queue>#include<algorithm>#include<iomanip>#include<stack>using namespace std;#define FILE "dealing"#define up(i,j,n) for(int i=(j);i<=(n);i++)#define pii pair<int,int>#define LL long long#define mem(f,g) memset(f,g,sizeof(f))namespace IO{char buf[1<<15],*fs,*ft;int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;}int read(){int ch=gc(),f=0,x=0;while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=gc();}while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc();}return f?-x:x;}int readint(){int ch=getchar(),f=0,x=0;while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}return f?-x:x;}}using namespace IO;const int maxn=201000,inf=1000000000;int n,m;int ch[maxn],l[maxn],r[maxn],k[maxn],f[maxn];struct node{int k,id;bool operator<(const node& b)const{return k<b.k;}}Cnt[maxn];int L=0;namespace OI{#define mid ((l+r)>>1)const int maxm=20000000;int root=0,c[maxn][2],id[maxn],cnt=0;//權值線段樹LL sum[maxm],flag[maxm];int d[maxm][2],len=0;//區間線段樹int x,y,key;void pushdown(int o,int l,int r){if(flag[o]){if(l!=r&&!d[o][0])d[o][0]=++len;if(l!=r&&!d[o][1])d[o][1]=++len;sum[d[o][0]]+=flag[o]*(mid-l+1);sum[d[o][1]]+=flag[o]*(r-mid);flag[d[o][0]]+=flag[o];flag[d[o][1]]+=flag[o];flag[o]=0;}}void change(int l,int r,int& o){if(l>y||r<x)return;if(!o)o=++len;if(l>=x&&r<=y){sum[o]+=r-l+1;flag[o]++;return;}pushdown(o,l,r);change(l,mid,d[o][0]);change(mid+1,r,d[o][1]);sum[o]=sum[d[o][1]]+sum[d[o][0]];}void insert(int l,int r,int& o){if(l>key||r<key)return;if(!o)o=++cnt;change(1,n,id[o]);if(l==key&&r==key)return;insert(l,mid,c[o][0]);insert(mid+1,r,c[o][1]);}void init(int l,int r,int k){x=l,y=r,key=k;insert(1,L,root);}int query2(int l,int r,int o){if(l>y||r<x||!o)return 0;if(l>=x&&r<=y)return sum[o];pushdown(o,l,r);return query2(l,mid,d[o][0])+query2(mid+1,r,d[o][1]);}int query1(int l,int r,int o){if(!o||r<=key)return 0;if(l>key)return query2(1,n,id[o]);return query1(l,mid,c[o][0])+query1(mid+1,r,c[o][1]);}int Query(int l,int r,int val){x=l,y=r,key=val;return query1(1,L,root)+1;}int Q(int l,int r,int k){int left=1,right=L,midd,p;while(left+1<right){midd=(left+right)>>1;if(Query(l,r,midd)>k)left=midd;else right=midd;}if(Query(l,r,left)>k&&Query(l,r,right)<=k)return right;else return left;}}using namespace OI;void print(int *a,int n){up(i,1,n)printf("%d ",a[i]);cout<<endl;}int main(){freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);n=read(),m=read();up(i,1,m){ch[i]=read(),l[i]=read(),r[i]=read(),k[i]=read();if(ch[i]==1)Cnt[++L].k=k[i],Cnt[L].id=i;}sort(Cnt+1,Cnt+L+1);up(i,1,L)f[Cnt[i].id]=i;int pre=0,d=(1LL<<8)-1;up(i,1,m){l[i]^=(pre&d),r[i]^=(pre&d);if(!l[i])l[i]=1;if(!r[i])r[i]=1;if(l[i]>r[i])swap(l[i],r[i]);if(ch[i]==1)init(l[i],r[i],f[i]);if(ch[i]==2)printf("%d\n",pre=Cnt[Q(l[i],r[i],k[i])].k);}return 0;}
[樹套樹]K大數查詢