萌新求调或小hack数据
查看原帖
萌新求调或小hack数据
219099
pocafup楼主2020/10/15 05:49

刚学CDQ,从昨天写到现在5hr+总算过了自己造的小数据和样例,但是交上去全部wa。

代码应该不算长,核心代码就十几行,但是我脑子不清晰搞不出来

思路大概是求出初始逆序对,然后对于每个数判断删除后和对左右两边未删除且存在的逆序对产生的贡献,最后根据时间往下减。

求dalao帮个忙qwq

调试代码没删,有带注释

#include <stack>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <cstring>
#include <queue>
#include <map>
#include <set>

using namespace std;
//reader and writer
#define int long long
void setIn(string s) { freopen(s.c_str(),"r",stdin); }
void setOut(string s) { freopen(s.c_str(),"w",stdout); }
//file io
void setIO(string name) {
	freopen((name+".in").c_str(),"r",stdin);
	freopen((name+".out").c_str(),"w",stdout);
}
//read int
inline int read(){
    register int a=0,f=1;register char c;
    while((c=getchar())<'0')if(c=='-')f=-1;
    while(c>='0')a=a*10+(c^48),c=getchar();
    return a*f;
}
//write int
inline void write(int s) {
  if (s<0) s =-s,putchar('-');
  if (s>9) write(s/10),putchar(s%10+'0');
  else putchar(s+'0');
}
//write int with space
inline void Write(int s){
  write(s);
  printf(" ");
}
//write int with endl
inline void writeln(int s){
  write(s);
  puts("");
}
//get char
inline char get(){
  char re = getchar();
  while(re=='\r' || re=='\n') re = getchar();
  return re;
}
//get string
inline string Get(){
  string s=""; char re;
  while(isalpha(re=getchar())) s+=re;
  return s;
}
//template stuff
typedef vector<int> vi;
typedef long long ll;
#define ft front()
#define bk back()
#define pq priority_queue
#define sz(x) (int)(x).size()
#define mp make_pair
#define endl '\n'
#define pp pair<int,int>
#define f first
#define s second
#define pb push_back
#define mem(s,v) memset(s,v,sizeof(s))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define FOR(i,a,b) for (int i=a;i>=b;i--)
#define Trav(a,b) for(auto a : b)
#define trav(i,u) for(int i=head[u];i;i=edge[i].nxt)
int Mod(int a, int p=(int)(1e9+7)){return a<p ? a : a%p;}
int chkmax(int a, int b){return a>b?a:b;}
int chkmin(int a, int b){return a<b?a:b;}
int qpow(int base, int times, int p=0){int ans=1;if (p)base%=p;while(times){if(times&1) {ans=ans*base; if(p) ans%=p;}times>>=1;base=base*base;if (p) base%=p;}return ans;}
int MaxVal(int a, int b, int *val){int re = 0;For(i,a,b) re = chkmax(re,val[i]);return re;}
int MinVal(int a, int b, int *val){int re = 1e9;For(i,a,b) re = chkmin(re,val[i]);return re;}


//namespace

const int MAXN = 1e5+5;
const int MAXM = 1e5+5;
const int mod = 1e9+7;
int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
int n,m,t,pos[MAXN],k,tot,cnt2,Ans[MAXN],head[MAXN],res;
namespace BIT{
  #define lowbits(x) (x&-x)
  int bit[MAXN];
  void update(int num, int posi){
    for (int i=posi;i<MAXN;i+=lowbits(i)) bit[i]+=num;
  }
  int query(int f){
    int ans = 0;
    for (int i=f;i;i-=lowbits(i))ans+= bit[i];
    return ans;
  }
  #undef lowbits
}
using namespace BIT;

namespace CDQ{
  struct Edge{
    int a,b,c,cnt;
    bool operator < (const Edge &oth) const{
      return a<oth.a || (a==oth.a && c<oth.c) || (a==oth.a && c==oth.c && b>oth.b);
    }
    bool operator == (const Edge &oth) const{
      return a==oth.a && b==oth.b && c==oth.c;
    }
  }edge[MAXN],te[MAXN];
  bool cmp(Edge v1, Edge v2){return v1.c<v2.c || (v1.c==v2.c && v1.b>v2.b);}

  inline void cdq(int l, int r){
    if (l==r) return;
    // cout << l << " " << r << endl;

    int mid = (l+r)>>1;
    cdq(l,mid); cdq(mid+1,r);//分治
    sort(edge+l,edge+1+mid,cmp);
    sort(edge+1+mid,edge+r+1,cmp);//模板
		int L = mid;//计算删除每个右边的数会产生的逆序对贡献
		// For(i,l,r) cout << "id :  " << edge[i].a << " val : " <<edge[i].b << " time :  " << edge[i].c << endl;

		// puts("");
    for (int R=r;R>=mid+1;R--){

      while(edge[L].c>=edge[R].c && L>=l) update(1,edge[L].b),L--;
			// cout << "R_val " << R << " " << edge[R].b << endl;
      edge[R].cnt+=query(n)-query(edge[R].b);
      // cout << "cnt " << L << " " << edge[R].b << " " << edge[R].cnt << endl;
    }
    FOR(i,mid,L+1) update(-1,edge[i].b);//FOR是倒叙枚举,For是正序
    int R = mid+1;
    //计算左边的
    for (int L=l;L<=mid;L++){
      while(edge[L].c<=edge[R].c && R<=r) update(1,edge[R].b),R++;
      edge[L].cnt+=query(edge[L].b);
      // cout << "cnt2    " << R << " " << edge[L].b << " " << edge[L].cnt << endl;

    }
    For(i,mid+1,R-1) update(-1,edge[i].b);
		// For(i,l,r) cout << edge[i].cnt << " ";
		// puts("");
  }
}
using namespace CDQ;

signed main(){
  n = read(); m = read();
  For(i,1,n)edge[i].a=i,edge[i].b=read(),head[edge[i].b] = i,edge[i].c=m+1;
  For(i,1,m) edge[head[read()]].c=i;
  For(i,1,n) res+=query(n)-query(edge[i].b), update(1,edge[i].b);//初始逆序对
  mem(bit,0);
  writeln(res);
  // For(i,1,n) writeln(edge[i].c);
  // For(i,1,n){
  //   if (i^1 && te[i]==te[i-1]) edge[tot].val++;
  //   else edge[++tot] = te[i];
  // }
	// For(i,1,n) cout << edge[i].val << endl;
  cdq(1,n);//求出删除每个点对答案的贡献
	// For(i,1,tot) cout << edge[i].val << " " << edge[i].cnt << endl;
  For(i,1,n) Ans[edge[i].c]+=edge[i].cnt;
  For(i,1,m-1) writeln(res-=Ans[i]);
}
*/
2020/10/15 05:49
加载中...